本鱼拟成立工作室承接项目开发/软件定制/云设施开发运维/办公设备技术支持等,如您有相关需求,欢迎来询 | ::博客文章推荐::

12306订票客户端 FOR .NET 演示项目 【3】流程分析和项目规划

: 原创作品 木魚 6714℃ 7评论

本系列文章

  1. 12306订票客户端 FOR .NET 演示项目 【7】登录9年前 (2015-08-18)
  2. 12306订票客户端 FOR .NET 演示项目 【6】验证码输入9年前 (2015-08-12)
  3. 12306订票客户端 FOR .NET 演示项目 【5】获得余票数据9年前 (2015-06-10)
  4. 12306订票客户端 FOR .NET 演示项目 【4】界面框架&基础数据初始化9年前 (2015-06-08)
  5. 12306订票客户端 FOR .NET 演示项目 【3】流程分析和项目规划9年前 (2015-05-28)
  6. 12306订票客户端 FOR .NET 演示项目 【2】准备工具9年前 (2015-05-22)
  7. 12306订票客户端 FOR .NET 演示项目 【1】项目概况9年前 (2015-05-19)

FSLIB.NETWORK 网络库系列文章

  1. 12306订票助手.NET V10.6.1 发布8年前 (2016-09-01)
  2. 开源 FSLIB.NETWORK 库 2.2.0.08年前 (2016-08-02)
  3. FSLIB.NETWORK手册(1) · 基本概念和流程8年前 (2016-05-05)
  4. 原创FSLib.Network库更新 2.0.0 版8年前 (2016-04-05)
  5. 原创FSLib.Network库更新 1.6.0版(目前专注于HTTP的高性能高易用性网络库)9年前 (2015-12-13)
  6. 玩具系列:批量QQ群签到工具v2 (暂时屏蔽自定义位置功能)9年前 (2015-08-29)
  7. 玩具系列:批量QQ群签到工具(支持自定义位置)9年前 (2015-08-28)
  8. 12306订票助手.NET 8.0.8 发布9年前 (2015-08-21)
  9. 12306订票客户端 FOR .NET 演示项目 【7】登录9年前 (2015-08-18)
  10. 12306订票客户端 FOR .NET 演示项目 【6】验证码输入9年前 (2015-08-12)
  11. 12306订票客户端 FOR .NET 演示项目 【5】获得余票数据9年前 (2015-06-10)
  12. 原创FSLib.Network库发布 1.5 版9年前 (2015-06-09)
  13. 12306订票客户端 FOR .NET 演示项目 【4】界面框架&基础数据初始化9年前 (2015-06-08)
  14. 12306订票客户端 FOR .NET 演示项目 【3】流程分析和项目规划9年前 (2015-05-28)
  15. 12306订票客户端 FOR .NET 演示项目 【2】准备工具9年前 (2015-05-22)
  16. 12306订票客户端 FOR .NET 演示项目 【1】项目概况9年前 (2015-05-19)
  17. 原创FSLib.Network库发布 1.4 版9年前 (2015-05-08)
  18. 放一个抓取网页的信息监控小工具源码9年前 (2015-04-27)
  19. FSLib.Network网络库使用教程[2] 实例教程·美女们快到硬盘里来!9年前 (2015-01-30)
  20. FSLib.Network网络库使用教程[1] 基本使用9年前 (2015-01-19)
  21. 原创FSLib.Network库(目前专注于HTTP的高性能高易用性网络库)9年前 (2015-01-18)

3.1 本章前言

从本章开始,将会涉及到具体的开发过程。工欲善其事,必先利其器。话虽如此,但准备工具之前知己知彼还是比较重要的……

3.2 12306流程分析

这里我们从一个典型的用户订票流程来考虑并设计流程。

注意:这里同时已经设置好了Fiddler和过滤器以抓取所有请求,供后面使用。如果此时你还没有进行这样的操作,在这之后每一步可能都需要临时分析,会花费不少多余的时间,强烈建议你现在就抓取一个完整的流程记录。相关的内容请参考上一节。

首先用户进入了查票入口,选择日期和地点。这里以经典的北京上海为例,时间选择的是7月20日,这里的信息不是关键的信息,可以根据你自己的需要来设置。

ticket_12306_demo_3_1

 

点击查询后,会跳转到查询页面,并显示查询结果。

ticket_12306_demo_3_2

这里假定我们要定G1次列车,点击预定按钮,此时会发现弹出了登录对话框。

ticket_12306_demo_3_3

输入用户名和密码并选择验证码后登录,相信我你也许会看到这个对话框。

ticket_12306_demo_3_5

这时候你要做的事情应该是刷新页面后重试。这里也看到,虽然提示你如果正在使用XXXX……但其实是废话,在12306的官网上这种事情也司空见惯。

登录成功后会跳转到订单页面。

ticket_12306_demo_3_4

选择乘客并选择验证码后,点击提交订单,会弹出来提交确认。

ticket_12306_demo_3_6

 

点击确认后,提交订单,此时进入排队界面

ticket_12306_demo_3_7

排队如果成功的话,那么就会自动跳转到付款页面。

ticket_12306_demo_3_8

至此,一个比较常规的订单流程就完成了。

3.3 保存Fiddler抓包记录

Fiddler的菜单“File”-“Save”中,保存所有的记录以便于后续分析。

ticket_12306_demo_3_9

 

提示:上图中看到很多带有绿色背景色的记录,这是因为启用了Fiddler的“Make Javascript Pretty”功能(在“Rules”菜单下)。这个功能可以让经过Fiddler发出去的、浏览器收到的脚本文件就已经是格式化好的,以便于分析。如果不启用此功能,可以在浏览器的开发者工具中做二次格式化。

3.4 需要的基础数据和流程分析

从之前的流程记录中,我们可以看到大概的流程是这样的。

ticket_12306_demo_3_9

用户可能有两种操作,先登录再查票,或先查票再登录,登录后提交订单。为了简便起见,这里始终直接允许查票,点击预定的时候再看看是否已经登录,没登录的话提示登录后再提交。

从图中右侧可以看到需要使用的数据。在不同的阶段需要用到不同的数据对象,使用时机和准备时机大致分为以下几种:

  1. 车站数据:属于基础数据,使用过程中不会变。因此我们把这部分数据的初始化放在程序一开始就进行
  2. 余票信息:用来提交订单并供用户查看的车票信息,在查票的过程中出现,每次查询均会获得余票信息
  3. 联系人数据:提交订单的时候需要使用,和账户有关系,因此这部分数据在登录后加载一次,并且使用延迟加载(需要的时候再加载)
  4. 预定信息:选中准备提交的联系人以及其票种、席别信息,提交订单的时候用到,并且需要用户交互选择输入
  5. 排队信息:在订单提交成功后、系统出票前出现,用于检查排队进度

3.5 系统结构和模块设计

为了让开发简便流程清晰,对各功能组件进行划分,做到职责分明。根据以上的流程分析,我们把整个系统分为以下各个模块。

分类  模块名 功能说明 
界面(UI)  UI界面 负责所有数据的展示、用户交互操作等 
网络(Network) 网络模块 负责所有请求的发送和接收,以及HTTP请求状态的维护,将会被会话模块使用
服务(Service) 会话模块 维护用户的会话以及相关联的数据发送、接受等操作,同时维护在中间操作所需要的额外数据信息(如动态密钥等) 
服务(Service) 查票模块 完成查票的请求发送、接收和结果转换 
服务(Service) 订单提交模块 负责获得用户输入并组织数据以提交订单
服务(Service) 联系人模块  负责加载当前账户的联系人信息
服务(Service) 订单排队模块  在订单提交成功后,完成对排队信息的检测和等待,并反馈最终结果 
服务(Service) 车站数据管理模块 负责加载、检索车站信息
服务(Service) 验证码模块 负责加载验证码并验证用户验证码是否输入正确
服务(Service) 动态密钥模块 负责维护整个会话中所需要使用的任何额外状态数据
提示:动态密钥模块后面会详细涉及此模块,此处可暂时忽略——毕竟在没开始之前你是不知道还有这东西的,我之所以现在就写上完全是因为懒得后面编辑……

3.6 项目结构初始化

有了以上的划分后,先暂时把所有的项目结构规划出来。

ticket_12306_demo_3_10

3.6.1 Network/NetClient

namespace Ticket12306Demo.Network
{
    using FSLib.Network.Http;
 
    /// <summary>
    /// 基于FSLIB.NETWORK的网络层扩展,进一步抽象以便于后期提供功能
    /// </summary>
    class NetClient : HttpClient
    {
        /// <summary>
        /// 默认构造函数
        /// </summary>
        public NetClient()
        {
            
        }
    }
}

3.6.2 Service/Session

这是会话模块,自己实现并维护了一个NetClient对象,封装了当前的状态和HTTP会话模态。

namespace Ticket12306Demo.Service
{
    using Ticket12306Demo.Network;
 
    /// <summary>
    /// 表示当前的12306登录会话,以及一些必须的状态信息。
    /// </summary>
    class Session
    {
        public Session()
        {
            NetClient = new NetClient();
        }
 
        /// <summary>
        /// 获得当前使用的网络对象,每个网络对象都是会话关联的。
        /// </summary>
        public NetClient NetClient { getprivate set}
 
        /// <summary>
        /// 获得当前是否已经登录
        /// </summary>
        public bool IsLogined { getprivate set}
    }
}

3.6.3 Service/ServiceBase

这是一个抽象基类,用作其它服务的基础对象,用来提供一些常规的状态信息和交互服务。

namespace Ticket12306Demo.Service
{
    using Ticket12306Demo.Network;
 
    /// <summary>
    /// 通用的服务基类,提供一些额外的基础服务
    /// </summary>
    abstract class ServiceBase
    {
        protected ServiceBase(ServiceContext context)
        {
            ServiceContext = context;
        }
 
        /// <summary>
        /// 获得当前的服务上下文
        /// </summary>
        public ServiceContext ServiceContext { getprivate set; }
 
        /// <summary>
        /// 获得当前关联的12306会话
        /// </summary>
        public Session Session { get { return ServiceContext.Session} }
 
        /// <summary>
        /// 获得当前关联的网络访问对象
        /// </summary>
        public NetClient NetClient
        {
            get { return Session.NetClient}
        }
 
        /// <summary>
        /// 获得当前是否已经登录
        /// </summary>
        public bool IsLogined { get { return Session.IsLogined} }
    }
}

3.6.4 Service下的其它服务模块

其它服务模块均基于 ServiceBase,完成各指定的功能。当然,现在还都是空架子。当前所有的模块都类似于以下的内容。

namespace Ticket12306Demo.Service
{
    /// <summary>
    /// 车票查询服务
    /// </summary>
    class TicketQueryService : ServiceBase
    {
        public TicketQueryService(ServiceContext context) : base(context)
        {
        }
    }
}

3.6.5 Service/ServiceContext

由于模块粒度较细,为了便于在UI层中使用也为了便于维护状态以及模块间调用,这里使用一个统一的对象进行上下文维护以及所有模块的维护。这个模块的构造函数中创建了所有的默认模块实例。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
 
namespace Ticket12306Demo.Service
{
    /// <summary>
    /// 服务状态上下文
    /// </summary>
    class ServiceContext
    {
        public ServiceContext()
        {
            Session = new Session();
            DynamicDataService = new DynamicDataService(this);
            OrderQueueService = new OrderQueueService(this);
            OrderSubmitService = new OrderSubmitService(this);
            PassengerService = new PassengerService(this);
            StationDataService = new StationDataService(this);
            VerifyCodeService = new VerifyCodeService(this);
            TicketQueryService = new TicketQueryService(this);
        }
 
        /// <summary>
        /// 获得当前的会话状态
        /// </summary>
        public Session Session { getprivate set}
 
        /// <summary>
        /// 获得当前的动态密钥服务
        /// </summary>
        public DynamicDataService DynamicDataService { getprivate set}
 
 
        /// <summary>
        /// 获得当前的订单排队服务
        /// </summary>
        public OrderQueueService OrderQueueService { getprivate set}
 
        /// <summary>
        /// 获得当前的订单提交服务
        /// </summary>
        public OrderSubmitService OrderSubmitService { getprivate set}
 
        /// <summary>
        /// 获得当前的联系人服务
        /// </summary>
        public PassengerService PassengerService { getprivate set}
 
        /// <summary>
        /// 获得当前的车站数据服务
        /// </summary>
        public StationDataService StationDataService { getprivate set}
 
        /// <summary>
        /// 获得当前的验证码服务
        /// </summary>
        public VerifyCodeService VerifyCodeService { getprivate set}
 
        /// <summary>
        /// 获得当前的查票服务
        /// </summary>
        public TicketQueryService TicketQueryService { getprivate set}
    }
}
注意:为了简化设计,这里并没有使用任何的动态构建服务以及接口。有兴趣的话可以自己对这里的设计做出重构 80.gif

3.6.6 UI

UI目录下的均为界面的东西,根据类型的不同进行了大致的划分(控件or窗体),现在仅有一个空空如也的MainForm

79.gif

3.7 本章总结

本章到此结束,下章开始正式开工写代码  0024.gif 

 

喜欢 (9)
发表我的评论
取消评论
表情

Hi,您需要填写昵称和邮箱!

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址
(7)个小伙伴在吐槽
  1. 等着4出来

    Daple2015-06-05 16:05 回复
  2. 12306订票客户端 FOR .NET 演示项目 【4】敲代码15.gif

    那个同学2015-06-04 15:46 回复
  3. 那个 Make Javascript Pretty 在哪? 没找到

    那个同学2015-05-29 15:32 回复
    • 确定你是最新的Fiddler,在rules菜单下。

      木魚2015-05-31 22:52 回复
      • Fiddler 4.5.1.0 还是没有

        那个同学2015-05-31 22:58 回复
        • 那个是个Fiddler插件,需要装一下

          lee2015-09-15 15:45 回复
  4. 0040.gif真是效率

    那个同学2015-05-28 18:51 回复