转载

Webx 学习笔记

最近在做一个简单的搜索工具, 目的是让用户能够更快捷的查找到合适自己的测试用例.

考虑到大多数身边的小伙伴都用 webx 来进行搭建服务, 而且加上最近已经有部分业务已经用到了 webx, 所以决定上 webx 这条已经运行了很久的大船..

首先贴上 webx 的 官方首页

先创建一个工程

mvn archetype:generate /
 -DgroupId=com.alibaba.webx /
 -DartifactId=tutorial1 /
 -Dversion=1.0-SNAPSHOT /
 -Dpackage=com.alibaba.webx.tutorial1 /
 -DarchetypeArtifactId=archetype-webx-quickstart /
 -DarchetypeGroupId=com.alibaba.citrus.sample /
 -DarchetypeVersion=1.8 /
 -DinteractiveMode=false

接着执行 mvn jetty:run-war 之后在浏览器里打开 localhost:8081 就能看到例子的样子了.

这样一个简单的 webx 应用就可以运行起来了

粗略的看了下例子的源码,但发现生成的几个例子的 java 类并没有明显的调用关系.

那么web 程序是如何run 起来的呢.

接着就产生了如下几个疑问:

1. execute 函数为何能够被调用到

2. doChinese 函数为何能够被调用到 3. JAVA 类如何与 vm 文件对应起来

4. 为什么链接的结尾有 do , htm ,分别有什么意义

5. 表单验证的运行原理是什么

6. 请求过来之后的处理流程

7. 如何满足我的要求

1. execute 函数为何能够被调用到,doChinese 函数为何能够被调用起来

先看看 execute 函数, 随便找一个 execute 函数,加上断点,看看调用栈

Webx 学习笔记

能够看到执行 execute 函数的地方是 performScreenModule

大致的代码是这样的

/** 执行screen模块。 */
  protected Object performScreenModule(TurbineRunData rundata) {
      ModuleFinder finder = new ModuleFinder(rundata.getTarget());

      // 如果设置了template,则默认打开layout
      rundata.setLayoutEnabled(true);

      try {
          Module module = finder.getScreenModule();

          // 当指定了templateName时,可以没有的screen module,而单单渲染模板。
          // 这样就实现了page-driven,即先写模板,必要时再写一个module class与之对应。
          if (module != null) {
              // 将event传入screen。
              ScreenEventUtil.setEventName(rundata.getRequest(), finder.event);

              try {

                  if (module instanceof ModuleReturningValue) {
                      return ((ModuleReturningValue) module).executeAndReturn();
                  } else {
                      module.execute();
                  }
              } finally {
                  ScreenEventUtil.setEventName(rundata.getRequest(), null);
              }
          } else {
              if (isScreenModuleRequired()) {
                  throw new ModuleNotFoundException("Could not find screen module: " + finder.moduleName);
              }
          }
      } catch (ModuleLoaderException e) {
          throw new WebxException("Failed to load screen module: " + finder.moduleName, e);
      } catch (Exception e) {
          throw new WebxException("Failed to execute screen: " + finder.moduleName, e);
      }

      return null;
  }

从代码可以看出,首先找到对应的 module, 接着执行 executeAndReturnexecute

我们接着 finder.getScreenModule() 继续深入下去,就会找到最终 module 生成的地方

public class DataBindingAdapterFactory extends AbstractDataBindingAdapterFactory {
    public Module adapt(String type, String name, Object moduleObject) {
        ModuleInfo moduleInfo = new ModuleInfo(type, name);
        Class<?> moduleClass = moduleObject.getClass();
        Method executeMethod = getMethod(moduleClass, "execute");

        if (executeMethod != null) {
            FastClass fc = FastClass.create(moduleClass);
            FastMethod fm = fc.getMethod(executeMethod);

            // 对于action,可被“跳过”执行。
            boolean skippable = "action".equalsIgnoreCase(type);

            return new DataBindingAdapter(moduleObject, getMethodInvoker(fm, moduleInfo, skippable));
        }

        return null;
    }
}

到这里应该就可以得出结论了, execute 是在代码里写死了, doXXX 也是一样的… 至于 moduleClass 的获取方式是直接从 request url 里解析出来的,所以 java class 的名字需要有与url 一一对应起来

记录一张官方文档的图片说明 webx Turbine 的组成部分

Webx 学习笔记

• Screen,代表页面的主体。

• Layout,代表页面的布局。

• Control,代表嵌在screen和layout中的页面片段。

2. 为什么链接的结尾有 do , htm 分别有什么意义

这个可以在 Webx3_Guide_Book.pdf 4.3 处理页面的基本流程里找到.

‘.do’ 后缀不是必须的,另外也是可以自己定义的.例如 “.go” 也是可以的.但需要在 pipeline.xml 里定义好

3. 表单验证的运行原理是什么

这个问题也可以在 Webx3_Guide_Book.pdf 第九章得到完美的解答. 了解相应的规则就好

4. 请求过来之后的处理流程以及如何满足我的要求

当一个HTTP请求到达时,首先由WebxFrameworkFilter, 这个是在 web.xml里约定好的…

不过在知道 execute 如何被调用到之后, 你就会发现 execute 函数是可以带参数的,所以对于我来说只需要改造一下 execute 函数就可以满足我的需求了

public void execute(HttpServletResponse response, HttpServletRequest request) throws Exception {
    // 设置content type,但不需要设置charset。框架会设置正确的charset。
    response.setContentType("text/plain");

    // 如同servlet一样:取得输出流。
    PrintWriter out = response.getWriter();

    Map map = request.getParameterMap();

    out.println(searchResultFromParam(map));
}

这样客户端发送 get 或者 post 请求, webx 就可以处理并返回查询结果…

OK 暂时就到这里吧, 以后如果需要深入了解,再来追加….

学习 webx 花了八个番茄钟, 写该文章花了一个番茄钟.

原文  http://blog.qianlicao.cn/technology/2017/02/10/notes-of-webx/
正文到此结束
Loading...