简介:WADE开发文档面向使用WADE框架进行企业级Java Web开发的中初级开发者,系统梳理框架的基本功能与开发步骤,帮助读者快速上手项目搭建与版本改造。文档围绕新建项目与开发改造两条主线展开:新建项目部分讲解如何借助quickstart工具生成空项目,并说明build.properties中项目名称、项目目录、WADELIB包路径、编译省份等配置项的含义;开发改造部分按WADE2.52至2.59各版本列出建议改造点,涉及JDK版本配置、输入框回车动作控制、集群缓存共享、客户端DataMap与DatasetList数据格式统一、页面命名调整等内容,便于读者对照自身框架版本排查兼容性问题。资源包为1个doc文件,约3.24MB,结构紧凑,适合作为日常开发查阅手册。目前已有974人学习,可供需要理解WADE框架配置体系与升级改造思路的开发者参考。
1. 从一次 ant newproject 翻车说起:WADE 环境到底装什么
接手一个老系统维护任务,第一件事不是看代码,而是把开发环境跑起来。WADE 这套框架的入门动作很固定:拿到 quickstart,改build/build.properties,跑ant newproject生成空项目。听起来三步就完事,但我见过太多人卡在第一步——项目名改了,OLD_NAME系列没改,生成出来的目录里还残留 quickstart 的页面配置,编译能过,一跑菜单全是别人的东西。更隐蔽的坑是WADELIB_HOME路径写错,ant 报找不到build_wadelib.xml,新手对着报错能查一下午。这篇笔记按我实际装环境的顺序走:先列清 JDK、Ant、目录结构这些前置条件,再一步步做新建项目、配 build.properties、跑编译,最后落到新增/修改/删除/导入这些日常开发动作怎么验证跑通。适合刚接手 WADE 项目的开发者,也适合想把老环境迁移到新机器上的熟手。
2. 装前把环境列清:JDK、Ant 与 wadelib 目录布局
2.1 版本选择:JDK_VERSION 到底填 1.4 还是 1.5
WADE 2.59 起,build.properties里多了一个必填项JDK_VERSION,取值只有1.4和1.5两个。这个参数不是随便填的,它决定 ant 编译时用哪个版本的 javac 目标,也决定打出来的包能不能在 jdk1.4 的运行环境里部署。我一般会先确认目标服务器的 JDK 版本:如果生产还是 1.4,就填1.4,否则编译出来的 class 文件版本偏高,部署上去直接UnsupportedClassVersionError。开发机本地装 JDK 1.5 或更高都没问题,编译目标由这个参数控制,不用为了迁就老环境把本地 JDK 降级。
# build/build.properties 中与 JDK 相关的配置 # 编译目标 JAVA 版本,取值 1.4 或 1.5 # 生产运行环境是 jdk1.4 时必须填 1.4 JDK_VERSION = 1.4这段配置的逻辑是:ant 在编译时会读取JDK_VERSION,拼出对应的source和target参数传给 javac。填1.4时生成的字节码能在 1.4 的 JVM 上跑,填1.5则要求运行环境至少 1.5。参数本身没有默认值兜底,漏写的话编译阶段就可能报错,所以新建项目后第一件事就是把它补上。
2.2 目录布局:wadelib 和应用目录必须同级
WADE 的编译依赖 wadelib 包,build.properties里用WADELIB_HOME指向它。官方建议 wadelib 和应用目录放在同一级,这样相对路径../../../wadelib/wadelib才能正确解析。我实际装的时候会先把目录摆成这样再动手:
# 推荐的目录结构,wadelib 与业务应用同级 workspace/ ├── wadelib/ │ ├── wadelib/ # WADELIB 包本体 │ └── build/ │ └── build_wadelib.xml └── wade-quickstart/ # quickstart 解压后的应用目录 ├── build/ ├── etc/ ├── src/ └── web/如果因为磁盘规划原因没法同级,就必须改build/build.xml里引入build_wadelib.xml的那行配置,把路径改成实际的相对或绝对路径,例如../../wadelib/build/build_wadelib.xml。这一步改错的表现是 ant 启动就报Cannot find build_wadelib.xml,跟项目代码一点关系都没有,纯粹是路径问题。
2.3 Ant 与 ant-contrib.jar:打包发布的前置依赖
开发阶段用ant all编译就够了,但测试打包发布要用ant allwar,而allwar目标依赖ant-contrib.jar。这个 jar 不在 Ant 自带库里,需要单独下载后放进 Ant 的lib目录,或者通过-lib参数指定。我一般直接丢进ANT_HOME/lib,省得每次敲命令都带路径。装完可以用一条命令确认 Ant 能识别到它:
# 确认 ant 版本与 ant-contrib 是否可用 ant -version # 把 ant-contrib.jar 放进 ANT_HOME/lib 后,执行 allwar 目标验证 ant allwarant -version输出 Ant 版本号,确认 Ant 本身装好了;ant allwar能跑起来不报taskdef class net.sf.antcontrib... cannot be found,说明 ant-contrib 加载成功。这两个检查做完,环境的前置条件就算齐了。
3. 新建项目全流程:从 quickstart 到可编译的空工程
3.1 改 build.properties:PROJECT_NAME 与 OLD/NEW 三组名称
新建项目的核心动作是让 ant 把 quickstart 里的quickstart字样批量替换成新项目名。build.properties里除了PROJECT_NAME,还有OLD_NAME1/2/3和NEW_NAME1/2/3三组大小写变体,分别对应全小写、首字母大写、全大写。这三组必须一一对应改全,漏一组就会出现「目录名对了但类名还是 Quickstart」的混合状态。
# 项目名称,打包后的 jar/war 以此为准 PROJECT_NAME = wade-custmgr # 编译时的省代码,开发用 common,打包部署时选对应省份 PROVINCE_NAME = common # 原系统名称(quickstart),三组大小写变体 OLD_NAME1 = quickstart OLD_NAME2 = Quickstart OLD_NAME3 = QUICKSTART # 新系统名称,三组必须与上面一一对应 NEW_NAME1 = custmgr NEW_NAME2 = Custmgr NEW_NAME3 = CUSTMGRPROJECT_NAME决定最终产物的文件名,OLD_NAME*和NEW_NAME*决定源码、配置、页面里的字符串替换规则。PROVINCE_NAME在开发阶段固定写common,只有打包给具体省份部署时才改,这一点新手容易搞混,开发时填了省份代码,编译出来的东西跟本地环境对不上。
3.2 执行 ant newproject 并清理残留配置
配置改完,在build目录下执行ant newproject,ant 会在build目录下生成一个全新的空项目目录。生成之后还有一步不能省:删掉page.application和sidebar.html里 quickstart 保留的页面名称配置和菜单配置。这些是示例页面,不删的话新项目一启动菜单里全是 VIP 客户资料之类的演示入口,看着像没生成成功。
# 进入 build 目录执行新建项目 cd wade-quickstart/build ant newproject # 生成后检查新项目目录,确认名称替换完整 ls -d ../custmgr grep -r "quickstart" ../custmgr/etc/page.applicationant newproject读取build.properties里的替换规则,把模板工程复制并重命名。执行完ls能看到新目录,grep在page.application里搜不到quickstart残留,说明替换干净了。如果还能搜到,多半是OLD_NAME某一组没改对,回去补上再重新生成。
3.3 编译验证:ant all 与 ant allwar 的取舍
开发阶段用ant all,它做的是编译加基础资源处理,速度快,适合改代码后频繁跑。测试打包发布用ant allwar,它会额外打 war 包,依赖 ant-contrib。两者的区别不只是产物,allwar还会走一遍打包相关的资源过滤,所以发布前必须用allwar验证一次,不能拿all的结果直接上线。
# 开发编译,默认目标 ant all # 测试打包发布,需要 ant-contrib.jar ant allwarant all成功后web/WEB-INF/classes下会有编译产物;ant allwar成功后会在输出目录生成以PROJECT_NAME命名的 war 包。第一次装环境时我建议两个都跑一遍,all验证编译链,allwar验证打包链,哪一步报错就定位到对应环节,比上线前才发现打不了包强。
4. 日常开发动作落地:增删改查与批量导入的配置要点
4.1 新增与修改:save 和 update 的区别决定数据会不会被清空
新增数据的流程是 HTML 表单、页面 Java 事件、Java Bean 方法三层。页面里用@wade:PageRedirect跳转到编辑页,Bean 里用dao.insert落库。真正容易翻车的是修改:save和update行为完全不同。update会把 data 里所有字段更新,表里原有但 data 没带的字段会被清空;save先查出原记录再覆盖,只改 data 里带的字段。部分更新必须用save,全量更新才用update。
// 修改时按主键和注销标记判断能否更新,部分更新用 save public boolean updateVipcust(PageData pd, IData data, String[] values) throws Exception { ExamplesDAO dao = new ExamplesDAO(pd); // 指定 VIP_ID 和 REMOVE_TAG 作为匹配条件,避免并发下改到已注销记录 return dao.save("TF_F_CUST_VIP", data, new String[] {"VIP_ID", "REMOVE_TAG"}, values); }这里save的第三个参数是匹配列名,第四个参数是对应的值。用VIP_ID加REMOVE_TAG双条件,是为了处理「打开页面后别人已经注销了这条记录」的并发场景,匹配不上就返回 false,页面层再提示「信息已被操作过」。如果换成update且 data 只带了部分字段,没带的列会被置空,这种数据丢失事后很难查。
4.2 删除与查看:绑定指定列避免误删误查
删除和查看都涉及按条件定位记录。删除用dao.delete,查看用dao.queryByPK,两者都支持在方法后追加列名数组,按指定列而不是默认主键来匹配。表没有主键或有联合主键时,这个参数就是必需的。
// 删除时按 VIP_ID 和 REMOVE_TAG 双条件,注销后不能再删 public boolean deleteVipcust(PageData pd, String vip_id, String remove_tag) throws Exception { ExamplesDAO dao = new ExamplesDAO(pd); IData data = new DataMap(); data.put("VIP_ID", vip_id); data.put("REMOVE_TAG", remove_tag); // 指定匹配列,避免只按主键删掉不该删的记录 return dao.delete("TF_F_CUST_VIP", data, new String[] {"VIP_ID", "REMOVE_TAG"}); }delete的第三个参数指定匹配列,data里放对应的值。查看同理,queryByPK追加new String[] {"VIP_ID", "REMOVE_TAG"}就能按双条件查唯一记录。这一步的取舍在于:条件列越多越安全,但索引要跟上,否则查询会慢,老系统里这种细节往往被忽略。
4.3 批量导入:XML 配置与 type=“1” 保住原始数据
批量导入的链路最长:import/xxx.xml配导入格式校验,export/xxximport.xml配失败数据导出,页面 Form 必须设enctype="multipart/form-data",还要有verifyAll、confirmForm、confirmInfo这些标准验证方法,否则后台拿不到数据。失败数据导出配置里,所有列建议设type="1",让数据以文本原样导出,不做格式转换。
<!-- 导入失败数据导出配置,全部列设 type="1" 保留原始输入 --> <sheet name="VIP 客户资料" desc="日程信息"> <header isshow="true" height="300"> <cell name="SCHE_SUBJECT" desc="日程主题" type="1" align="1" width="6000"/> <cell name="IMPORT_ERROR" desc="导入错误" type="1" align="1" width="10000"/> </header> </sheet>type="1"表示字符串,type="2"是数字,type="3"是时间。失败数据如果设了type="3"加format="yyyy-MM-dd HH:mm",用户填的2007-03-01会被转成2007-03-01 00:00,原始形式就丢了,用户拿着失败文件改都不知道原来填的什么。所以失败导出统一用type="1",这是血泪经验换来的配置习惯。
5. 避坑与排查:五条装环境时真踩过的坑
5.1 现象:ant newproject 后菜单还是 quickstart 的
原因:page.application和sidebar.html里的示例页面配置没删,或者OLD_NAME某一组大小写变体没改全,替换不彻底。解决:先grep -r "quickstart"扫一遍新项目目录,确认残留位置;补全OLD_NAME1/2/3后重新执行ant newproject,再手动清理page.application和sidebar.html的菜单项。
5.2 现象:编译报找不到 build_wadelib.xml
原因:WADELIB_HOME路径与实际目录不符,或 wadelib 没和应用目录同级。解决:确认WADELIB_HOME指向的目录下确实有web/WEB-INF/lib;不同级时改build/build.xml里引入build_wadelib.xml的路径,改成实际相对路径后重跑ant all。
5.3 现象:ant allwar 报 ant-contrib 相关类找不到
原因:ant-contrib.jar没放进 Ant 的 lib 目录,或放进去后没重启终端。解决:把 jar 丢进ANT_HOME/lib,新开终端执行ant -version确认环境变量生效,再跑ant allwar。用-lib参数临时指定也可以,但每次都要带,不如直接放 lib 省事。
5.4 现象:修改后部分字段变成空值
原因:用了update而不是save,data 里没带的字段被清空。解决:部分更新一律用save,它会先查原记录再覆盖;只有确认 data 包含全部字段时才用update换效率。改完在测试库上先跑一遍,对比更新前后的记录。
5.5 现象:导入失败文件里的日期格式被改了
原因:失败导出配置里列设了type="3"和format,导出时做了格式转换。解决:失败导出配置所有列改type="1",让数据以文本原样输出,IMPORT_ERROR列也设type="1"显示具体错误。
6. 装完怎么验证跑通:三条检查线和一个习惯
环境装完不能只看ant all绿了就收工,我一般走三条检查线。第一条是编译线:ant all和ant allwar各跑一次,前者验证开发编译,后者验证打包链和 ant-contrib 是否就位。第二条是配置线:新项目目录里grep -r "quickstart"应该零命中,page.application和sidebar.html里没有示例菜单残留,build.properties的JDK_VERSION、PROJECT_NAME、三组OLD/NEW名称都填了实际值。第三条是功能线:启动应用后走一遍新增、修改、删除、查看、批量导入,重点看修改时部分字段有没有被清空、导入失败文件里的原始数据格式有没有被改。
# 装完后的三条检查线,按顺序跑 cd wade-custmgr/build ant all && ant allwar # 编译线与打包线 grep -r "quickstart" ../custmgr/etc ../custmgr/web # 配置线,应无输出ant all && ant allwar用&&串联,前一个失败就不跑后一个,省得在错误状态上继续操作。grep扫etc和web两个目录,覆盖配置和页面,无输出说明替换干净。功能线没法用一条命令覆盖,只能手动点,但我会把「修改后字段是否被清空」作为必查项,因为这是save/update选错时最典型的症状。
| 检查项 | 命令或动作 | 通过标准 |
|---|---|---|
| 开发编译 | ant all | 无报错,classes 下有产物 |
| 打包发布 | ant allwar | 生成以 PROJECT_NAME 命名的 war |
| 名称替换 | grep -r "quickstart" | 无输出 |
| 部分更新 | 修改一条记录只改一个字段 | 其他字段保持原值 |
| 导入失败文件 | 故意导入一条错误数据 | 失败文件保留原始输入格式 |
这张表我一般贴在环境搭建的记录里,换机器或换人接手时照着跑一遍,比口头交接靠谱。从那以后我每次装 WADE 环境,都强制先跑grep -r "quickstart"再跑ant allwar,两个都过了才动业务代码,因为这两个动作分别卡住了名称替换和打包依赖这两个最容易翻车的点。希望帮到你。
本文还有配套的精品资源,点击获取