虽然有些开发人员选择用JavaScript实现应用程序,并使用客户机-服务器协议访问服务器端资源,但这有许多固有的缺点。您需要放弃静态类型(或添加另一层,如GWT)。类型安全由编译器强制执行,随着项目的复杂性和开发人员数量的增长,它的价值是无价的。此外,您需要设计一个客户机-服务器协议,并最小化通信和相关的往返延迟。最后,这种方法不适用于需要满足可访问性指导原则的应用程序或需要进行搜索引擎优化的应用程序,因此需要只有html版本的应用程序。Wt作为服务器端解决方案克服了这些问题,与JavaScript应用程序相比,它的交互性几乎没有损失。
Wt相对于其他服务器端方法的主要优势是它的小部件抽象。应用程序被定义为小部件的层次结构。其中一些小部件是通用的,由库提供(如按钮、行编辑、表视图等),而另一些则专门用于特定的应用程序(例如整个博客小部件)。小部件封装视图和行为方面,消费和产生事件,还参与URL处理,并可能与其他HTTP资源交互。通常情况下,小部件将实际的“逻辑”委托给模型,这种分层方法通常称为MVC。与页面或“部件”不同,小部件是现代web应用程序的真正可重用、可定制和可扩展的构建块(作为面向对象编程的典型代表)。实际的请求处理和呈现是抽象的,好处是可以根据配置和浏览器属性使用完整的页面呈现模型(纯HTML)或增量更新(Ajax/WebSockets)。
虽然Wt是用c++实现的,但它的主要焦点或新奇之处并不在于性能,而在于开发可维护的应用程序和广泛的内置小部件库。但是由于它在嵌入式系统中很流行并被广泛使用,您会发现性能和足迹也得到了优化,这得益于一个没有废话的API、周到的架构和c++…
在本教程中,我们将使用两个小程序来演示如何使用Wt创建web应用程序。在本教程之后,您应该很好地掌握了Wt应用程序是如何构建的,以及它如何为您提供管理复杂性的工具。
第一个应用程序是必须的Hello World应用程序,它介绍了库的两个关键概念:创建和更新小部件树以及对用户输入作出反应。第二个稍微大一点的应用是经典的刽子手游戏。这两个应用程序都包含在Wt源代码发行版中。
在浏览器窗口中呈现的用户界面由创建和维护小部件树定义。每一个Widget对应于一个矩形部件的用户界面,并管理其内容和行为。在Heart中,库在一次会话中负责两项任务:
(1)在web上以HTML/JavaScript的形式呈现这个小部件树浏览器,并跟踪作为增量更新的更改,以及同步用户输入并将事件从浏览器转发到这些小部件。
因为用户界面规范之间有明确的分离使用小部件树和树的呈现,库实现了Ajax的渲染优化可用。不仅库可以更新接口渐进地,还有其他技巧,如只渲染可见小部件在响应事件(或初始加载)期间发生变化,并在后台渲染隐藏小部件的更改。作为一个结果,初始响应和外观都得到了优化的后续小部件看起来很时髦。
另一个完全由库处理的方面是会话管理。对于每个新会话,它对应一个新用户访问web应用程序时,库会创建一个新的WApplication对象。作为一个开发者,你可以实现一个应用程序,就像一个单用户应用程序,除非您让用户与公共交互组件(如数据库)或相互配合,适用于哪种标准必须使用数据共享机制。
根据部署模型,库将把会话映射到专用的或共享的进程。当使用专用进程时,一个新的进程为每个不同的会话创建:这提供了不同会话的内核级隔离,这可能对高度安全敏感的应用程序。使用共享进程时新会话随机分配给一个可用进程去库。这降低了DoS攻击的危险,但需要更谨慎的编程,因为内存损坏会影响所有会话单个进程和会话不被任何其他机制隔离而是正确的编程。
有几个部署选项可用:
实现HTTP(S)和WebSockets。它不仅方便在
开发,也是一个高效的解决方案部署范围
从小型嵌入式系统或移动设备到多服务器
部署。
它允许Wt应用程序集成到现有的web服务器中
(如Apache, Lighttpd或Nginx)。
Windows平台,它允许Wt应用程序集成到
微软Internet信息服务器(IIS)。
#include <Wt/WApplication.h>
#include <Wt/WBreak.h>
#include <Wt/WContainerWidget.h>
#include <Wt/WLineEdit.h>
#include <Wt/WPushButton.h>
#include <Wt/WText.h>
class HelloApplication : public Wt::WApplication
{
public:
HelloApplication(const Wt::WEnvironment& env);
private:
Wt::WLineEdit *nameEdit_;
Wt::WText *greeting_;
};
HelloApplication::HelloApplication(const Wt::WEnvironment& env)
: Wt::WApplication(env)
{
setTitle("Hello world");
root()->addWidget(std::make_unique<Wt::WText>("Your name, please? "));
nameEdit_ = root()->addWidget(std::make_unique<Wt::WLineEdit>());
Wt::WPushButton *button = root()->addWidget(std::make_unique<Wt::WPushButton>("Greet me."));
root()->addWidget(std::make_unique<Wt::WBreak>());
greeting_ = root()->addWidget(std::make_unique<Wt::WText>());
auto greet = [this]{
greeting_->setText("Hello there, " + nameEdit_->text());
};
button->clicked().connect(greet);
}
int main(int argc, char **argv)
{
return Wt::WRun(argc, argv, [](const Wt::WEnvironment& env) {
return std::make_unique<HelloApplication>(env);
});
}
$ sudo apt-get install witty witty-dev witty-doc witty-dbg witty-examples
$ g++ -std=c++14 -o hello hello.cc -lwthttp -lwt
$ ./hello --docroot . --http-address 0.0.0.0 --http-port 9090