最近在做一个简单的搜索工具, 目的是让用户能够更快捷的查找到合适自己的测试用例.
考虑到大多数身边的小伙伴都用 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. 如何满足我的要求
先看看 execute
函数, 随便找一个 execute 函数,加上断点,看看调用栈
能够看到执行 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, 接着执行 executeAndReturn
或 execute
我们接着 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 的组成部分
• Screen,代表页面的主体。
• Layout,代表页面的布局。
• Control,代表嵌在screen和layout中的页面片段。
do
, htm
分别有什么意义 这个可以在 Webx3_Guide_Book.pdf
4.3 处理页面的基本流程里找到.
‘.do’ 后缀不是必须的,另外也是可以自己定义的.例如 “.go” 也是可以的.但需要在 pipeline.xml
里定义好
这个问题也可以在 Webx3_Guide_Book.pdf
第九章得到完美的解答. 了解相应的规则就好
当一个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 花了八个番茄钟, 写该文章花了一个番茄钟.