插件

在Treefrog中, 插件指动态库(共享库, DLL)用来扩展功能. 因为Treefrog有Qt插件系统, 如果标准功能不合适你可以创建一个新的插件. 目前为止, 可以创建的插件可以分为下面这些类型:

  • 记录插件(用来输出记录)
  • 会话存储插件(保存和读取会话)

如何创建插件

创建插件与如何为Qt创建插件的一模一样的. 为了说明这一点, 让我们来创建个记录插件. 首先, 我们将在plugin文件夹下创建一个工作目录.

> cd plugin 
> mkdir sample
  • 本质上, 可以选择任何地方作为工作目录, 但是当考虑路径方案时, 像前面提到的那样创建工作目录是一个好的方式.

我们将创建一个插件封装类(此例为TLoggerPlugin). 通过继承这个作为接口的类, 然后重写一些虚拟函数.

sampleplugin.h
---
class SamplePlugin : public TLoggerPlugin
{
    QStringList keys() const;
    TLogger *create(const QString &key);
};

在keys()方法中, 字符串(能够被插件支持的key)将以列表的形式返回. 在create()方法中, 对应这些key的logger的实例被创建, 并且用某种方式实现后返回一个指针.

在源文件中包含这个Qt插件后, 你可以通过设置宏注册这个插件,如下:

  • 第一个参数也可是任何字符串,如插件的名字
  • 第二个参数是插件类名.
sampleplugin.cpp
---
#include <QtPlugin>
   :
   :
Q_EXPORT_PLUGIN2(samplePlugin, SamplePlugin)

接下来, 我们创建一个函数来扩展这个插件(类). 我们将创建一个logger输出记录. 按上面的做法, 再次通过继承这个类, 然后重新一些虚拟函数.

samplelogger.h
---
class SampleLogger : public TLogger
{
public:
    QString key() const { return "Sample"; }
    bool isMultiProcessSafe() const;
    bool open();
    void close();
    bool isOpen() const;
    void log(const TLog &log);
    ...
};

接下来的目标是项目文件(.pro). 不要忘记将”plugin”添加到CONFIG参数!

TARGET = sampleplugin
TEMPLATE = lib
CONFIG += plugin
DESTDIR = ..
include(../../appbase.pri)
HEADERS = sampleplugin.h \
          samplelogger.h
SOURCES = sampleplugin.cpp \
          samplelogger.cpp
  • 使用include()包含appbase.pri文件是重要的.

然后, 当你构建时, 你可以生成一个可加载的动态插件. 每次保存插件到plugin文件夹时, 不要有错误, 因为应用服务器(AP server)从这个目录加载插件. 更多关于插件系统的详细信息请参考Qt文档.

记录器插件

FileLogger是一个输出记录到文件的基本的记录器. 然而, 它可能不适合需求. 例如, 如果把记录像数据库一样保存或者希望交替保存记录的文件, 你可能想要使用插件机制来扩展功能.

按上面描述的那样, 在创建一个记录器插件后, 将插件放置在plug-in目录. 还有, 要让应用服务器加载需要更新logger.ini文件的配置信息. 将记录器的名字赋给loggers参数, 并用空格隔开. 下面的例子显示了它应该看起来像:

Loggers=FileLogger Sample

这样, 当你启动应用服务器时, 这些插件将被加载.

再说一次, 记录器的插件接口是一个类,如下面显示的:

  • 插件接口: TLoggerPlugin
  • 记录器接口: TLogger

关于记录器方法

要实现这个记录器, 你可以重写TLogger类的下面的方法:

  • key(): 返回记录器的名字.
  • open(): 加载后通过插件立即打开记录.
  • close(): 关闭记录.
  • log(): 输出记录. 这个方法是多线程调用的, 要使它能线程安全thread-safe.
  • isMultiProcessSafe(): 指示在多线程处理输出一个记录时是否安全. 安全则返回true, 不安全则返回false.

关于多线程处理安全方法: 当返回false(表示不安全)并且应用服务器运行在多线程模式, isMultiProcessSaft()方法在输出记录之前和之后每次都调用open()/close()(导致开销增加).
同时, 系统还有锁定/解锁信号保证不会有冲突. 当返回true时, 系统只会首先调用open()方法.

会话存储插件

在Treefrog中会话存储的标准方式有以下几种:

  • Cookies Session: 保存到cookies中.
  • DB Session: 保存到数据库中.需要创建表来实现.
  • File session: 保存到文件

如果这些都不合适, 你可以创建一个继承接口类的插件.

  • 插件接口: TSessionStorePlugin
  • 会话存储接口: TSessionStore

按照上面描述的方法, 通过重写继承类的虚拟函数, 你可以创建一个插件. 然后, 要加载这个插件, 你可以设置在application.ini文件的参数Session.StoreType为指定的值(只能选择一个). 默认的值为cookie.