Apache Geronimo 3.0.1 数据源与安全配置进阶详解
实测 Geronimo 3.0.1 数据源与安全两大进阶主题:TranQL Derby 连接池 plan 的六类部署报错逐个复现并给出可照抄的正确写法,dbdemo Web 应用经 @Resource 注入数据源并验证 Derby 持久化(rows 8→9→10),users.properties 的 {Simple} 加密、明文条目免重启生效、新增账号与组授权,全部回显实测采集。
Apache Geronimo 3.0.1 数据源与安全配置进阶详解
目标:在 Geronimo 3.0.1 上端到端跑通 Derby 连接池的部署与 Web 应用注入,把部署 plan 的六类报错逐一复现并给出正确写法;同时实测管理员口令加密、明文条目、新增账号与组授权的完整安全配置链路;全部命令与回显均已在 Ubuntu 22.04(x86_64)+ Zulu JDK 7 + Geronimo 3.0.1(内嵌 Tomcat 7.0.39.1)实测通过。
一、环境信息
- 操作系统:Ubuntu 22.04.5 LTS(x86_64)
- JDK:Zulu 7.56.0.11(OpenJDK 1.7.0_352),
JAVA_HOME=/opt/zulu7.56.0.11-ca-jdk7.0.352-linux_x64 - 服务器:Apache Geronimo 3.0.1 完整包,安装目录
G=/opt/geronimo-tomcat7-javaee6-3.0.1 - 管理凭据:默认账号
system / manager(本文涉及改密的示例口令统一用q1w2e3r4) - 连接池资源适配器:
org.tranql:tranql-connector-derby-embed-local:1.8(RAR 已随服务器内置)
export JAVA_HOME=/opt/zulu7.56.0.11-ca-jdk7.0.352-linux_x64
export PATH=$JAVA_HOME/bin:$PATH
G=/opt/geronimo-tomcat7-javaee6-3.0.1
RAR 在服务器仓库中的实测位置与文件:
ls -1 $G/repository/org/tranql/tranql-connector-derby-embed-local/1.8/
tranql-connector-derby-embed-local-1.8.rar
Derby 数据库文件的落盘目录(部署示例库后实测):
ls -1 $G/var/derby/
ActiveMRCDB
ArchiveMRCDB
MonitoringClientDB
SystemDatabase
UddiDatabase
demo-db
derby.log
💡 技术拓展:
SystemDatabase是 Geronimo 内置系统库,demo-db是本文示例创建的应用库;嵌入式 Derby 无需单独进程,数据库目录直接挂在服务器var/derby下,随服务器同生共死。
二、数据源配置总览
Geronimo 3.0.1 配数据源的固定套路是三件套:
- RAR:JDBC 资源适配器(Derby 本地嵌入版已在仓库中,无需下载);
- 部署 plan:一份 XML,声明 moduleId、依赖哪个 RAR、连接池名字与属性、池参数;
- deploy 命令:
deploy <rar路径> <plan路径>联合部署,成功后以car模块形态常驻。
plan 的正确骨架全文(文件路径 /opt/dbplan/demo-derby-pool-plan.xml,实测可部署):
<?xml version="1.0" encoding="UTF-8"?>
<connector xmlns="http://geronimo.apache.org/xml/ns/j2ee/connector-1.2">
<dep:environment xmlns:dep="http://geronimo.apache.org/xmlns/deployment-1.2">
<dep:moduleId>
<dep:groupId>demo</dep:groupId>
<dep:artifactId>demo-derby-pool</dep:artifactId>
<dep:version>1.0</dep:version>
<dep:type>car</dep:type>
</dep:moduleId>
<dep:dependencies>
<dep:dependency>
<dep:groupId>org.tranql</dep:groupId>
<dep:artifactId>tranql-connector-derby-embed-local</dep:artifactId>
<dep:version>1.8</dep:version>
<dep:type>rar</dep:type>
</dep:dependency>
</dep:dependencies>
</dep:environment>
<resourceadapter>
<resourceadapter-instance>
<resourceadapter-name>demo-derby-pool</resourceadapter-name>
<workmanager>
<gbean-link>DefaultWorkManager</gbean-link>
</workmanager>
</resourceadapter-instance>
<outbound-resourceadapter>
<connection-definition>
<connectionfactory-interface>javax.sql.DataSource</connectionfactory-interface>
<connectiondefinition-instance>
<name>jdbc/DemoDS</name>
<config-property-setting name="DatabaseName">demo-db</config-property-setting>
<config-property-setting name="CreateDatabase">true</config-property-setting>
<config-property-setting name="UserName"></config-property-setting>
<config-property-setting name="Password"></config-property-setting>
<connectionmanager>
<single-pool>
<max-size>10</max-size>
<blocking-timeout-milliseconds>5000</blocking-timeout-milliseconds>
<idle-timeout-minutes>15</idle-timeout-minutes>
<match-one/>
</single-pool>
</connectionmanager>
</connectiondefinition-instance>
</connection-definition>
</outbound-resourceadapter>
</resourceadapter>
</connector>
逐段说明:
- 根元素命名空间必须是
http://geronimo.apache.org/xml/ns/j2ee/connector-1.2(xml/ns连写,坑 4.2 有反例); dep:dependencies里声明 tranql RAR 依赖,部署器据此把 RAR 与 plan 绑定;workmanager/gbean-link引用服务器内置的DefaultWorkManager,是 schema 强制元素(坑 4.3);DatabaseName/CreateDatabase等 Derby 属性属于connectiondefinition-instance(坑 4.4);single-pool三参数是连接池的池化行为:最大 10 连接、取连接最多等 5 秒、空闲 15 分钟回收。
部署与验证:
./bin/deploy --user system --password manager deploy $G/repository/org/tranql/tranql-connector-derby-embed-local/1.8/tranql-connector-derby-embed-local-1.8.rar /opt/dbplan/demo-derby-pool-plan.xml
Deployed demo/demo-derby-pool/1.0/car
./bin/deploy --user system --password manager list-modules | grep demo-derby-pool
+ demo/demo-derby-pool/1.0/car
三、Web 应用引用数据源
3.1 Servlet 源码
验证用的 demo.DbDemoServlet(文件路径 /opt/dbsrc/src/demo/DbDemoServlet.java):
package demo;
import java.io.IOException;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.Statement;
import javax.annotation.Resource;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.sql.DataSource;
public class DbDemoServlet extends HttpServlet {
@Resource(name = "jdbc/DemoDS")
private DataSource ds;
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
resp.setContentType("text/plain;charset=UTF-8");
try {
Connection conn = ds.getConnection();
try {
Statement st = conn.createStatement();
try {
st.executeUpdate("CREATE TABLE demo_messages (id INT GENERATED ALWAYS AS IDENTITY PRIMARY KEY, msg VARCHAR(100))");
} catch (Exception e) {
// 表已存在则忽略
}
st.executeUpdate("INSERT INTO demo_messages (msg) VALUES ('hello-derby')");
ResultSet rs = st.executeQuery("SELECT COUNT(*) FROM demo_messages");
rs.next();
resp.getWriter().println("datasource=" + ds.getClass().getName());
resp.getWriter().println("rows=" + rs.getInt(1));
rs.close();
st.close();
} finally {
conn.close();
}
} catch (Exception e) {
throw new ServletException(e);
}
}
}
注入链路:@Resource(name = "jdbc/DemoDS") 与 web.xml 的 resource-ref 双声明(JNDI 名一致),Geronimo 在部署时把容器内真实的连接池绑定到 java:comp/env/jdbc/DemoDS。
3.2 web.xml 与 geronimo-web.xml
web.xml(路径 /opt/dbsrc/WEB-INF/web.xml):
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
version="3.0">
<display-name>dbdemo</display-name>
<servlet>
<servlet-name>DbDemoServlet</servlet-name>
<servlet-class>demo.DbDemoServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>DbDemoServlet</servlet-name>
<url-pattern>/db</url-pattern>
</servlet-mapping>
<resource-ref>
<res-ref-name>jdbc/DemoDS</res-ref-name>
<res-type>javax.sql.DataSource</res-type>
</resource-ref>
</web-app>
geronimo-web.xml(路径 /opt/dbsrc/WEB-INF/geronimo-web.xml)——声明 moduleId、依赖连接池模块、context-root 与 resource-ref 映射:
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://geronimo.apache.org/xml/ns/j2ee/web/tomcat-2.0.1">
<environment xmlns:dep="http://geronimo.apache.org/xmlns/deployment-1.2">
<dep:moduleId>
<dep:groupId>demo</dep:groupId>
<dep:artifactId>dbdemo</dep:artifactId>
<dep:version>1.0</dep:version>
<dep:type>war</dep:type>
</dep:moduleId>
<dep:dependencies>
<dep:dependency>
<dep:groupId>demo</dep:groupId>
<dep:artifactId>demo-derby-pool</dep:artifactId>
<dep:version>1.0</dep:version>
<dep:type>car</dep:type>
</dep:dependency>
</dep:dependencies>
</environment>
<context-root>/dbdemo</context-root>
<resource-ref>
<ref-name>jdbc/DemoDS</ref-name>
<resource-link>jdbc/DemoDS</resource-link>
</resource-ref>
</web-app>
两个实测确认过的命名空间要点:
geronimo-web.xml根元素可用http://geronimo.apache.org/xml/ns/j2ee/web-2.0.1或http://geronimo.apache.org/xml/ns/j2ee/web/tomcat-2.0.1(Tomcat 容器专用版);xmlns 变体会被拒(坑 4.5);dep:dependencies里的demo/demo-derby-pool/1.0/car不能省(坑 4.6)。
3.3 部署与端到端验证
./bin/deploy --user system --password manager deploy /opt/dbwar/dbdemo.war
Deployed demo/dbdemo/1.0/war @ /dbdemo
连续访问两次(每次请求插入一行并统计总行数):
curl -s --max-time 15 http://localhost:8080/dbdemo/db; echo
curl -s --max-time 15 http://localhost:8080/dbdemo/db; echo
datasource=org.tranql.connector.jdbc.TranqlDataSource
rows=8
datasource=org.tranql.connector.jdbc.TranqlDataSource
rows=9
datasource= 一行证实注入的是 TranQL 连接池代理而非裸驱动;rows 递增说明表与数据都在。持久化实测:undeploy 两个模块再完整重部署后,第三次访问:
datasource=org.tranql.connector.jdbc.TranqlDataSource
rows=10
应用模块的卸载/重装不影响 Derby 数据文件($G/var/derby/demo-db),要清数据只能删目录或用 SQL 清表。
四、部署 plan 六坑实测
以下六个错误现场全部实测复现,报错原文照抄(关键行),每坑给出修正方法。
4.1 坑一:只给 plan 不给 RAR
错误做法:
./bin/deploy --user system --password manager deploy /opt/dbplan/demo-derby-pool-plan.xml
org.apache.geronimo.common.DeploymentException: Unable to deploy demo-derby-pool-plan.xml: Cannot deploy the requested application module because no deployer is able to handle it. This can happen if you have omitted the J2EE deployment descriptor, disabled a deployer module, or if, for example, you are trying to deploy an EJB module on a minimal Geronimo server that does not have EJB support installed. (planFile=/root/plan/demo-derby-pool-plan.xml)
修正:connector plan 必须与 RAR 联合部署(deploy <rar> <plan>),plan 单独不能表达模块类型。
4.2 坑二:根命名空间写成 xmlns 变体
错误写法(只差 xml/ns 与 xmlns 之差):
<connector xmlns="http://geronimo.apache.org/xmlns/j2ee/connector-1.2">
/root/plan/pit2-wrongns-plan.xml:2:1: error: The document is not a connector@http://geronimo.apache.org/xml/ns/j2ee/connector-1.2: document element namespace mismatch expected "http://geronimo.apache.org/xml/ns/j2ee/connector-1.2" got "http://geronimo.apache.org/xmlns/j2ee/connector-1.2"
修正:用 http://geronimo.apache.org/xml/ns/j2ee/connector-1.2。特别注意:随服务器发布的 schema/geronimo-connector-1.2.xsd 内部声明的 targetNamespace 恰恰是错误的 xmlns 变体,照抄 schema 文件头会踩坑,以本节报错信息明示的 xml/ns 为准。
4.3 坑三:resourceadapter-instance 缺 workmanager
错误写法:resourceadapter-instance 内只有 resourceadapter-name。
/root/plan/pit3-nowm-plan.xml:21:7: error: cvc-complex-type.2.4c: Expected element 'workmanager@http://geronimo.apache.org/xml/ns/naming-1.2' before the end of the content in element resourceadapter-instance@http://geronimo.apache.org/xml/ns/j2ee/connector-1.2
修正:补上强制的 WorkManager 引用:
<workmanager>
<gbean-link>DefaultWorkManager</gbean-link>
</workmanager>
4.4 坑四:连接属性放错元素
DatabaseName/CreateDatabase 是 ManagedConnectionFactory 属性,必须放 connectiondefinition-instance。实测把它们挪进 resourceadapter-instance 后,schema 校验直接拒绝、部署即败:
/root/plan/pit4-propsinra-plan.xml:25:7: error: cvc-complex-type.2.4b: Element not allowed: config-property-setting@http://geronimo.apache.org/xml/ns/j2ee/connector-1.2 in element resourceadapter-instance@http://geronimo.apache.org/xml/ns/j2ee/connector-1.2
还有一种更隐蔽的历史实测形态:属性能通过部分校验路径进入 resourceadapter-instance 时,部署可成功但运行期必然报空库名(服务器日志实测,时间戳为当时采集点):
ERROR [[DbDemoServlet]] Servlet.service() for servlet [DbDemoServlet] in context with path [/dbdemo] threw exception [java.sql.SQLException: Failed to create database '', see the next exception for details.] with root cause
ERROR XBM0A: The database directory '/opt/geronimo-tomcat7-javaee6-3.0.1/var/derby' exists. However, it does not contain the expected 'service.properties' file. Perhaps Derby was brought down in the middle of creating this database. You may want to delete this directory and try creating the database again.
修正:两个属性只放 connectiondefinition-instance(见第二章骨架),resourceadapter-instance 里保留 name 与 workmanager 即可。
4.5 坑五:geronimo-web.xml 根命名空间用 xmlns 变体
错误写法:
<web-app xmlns="http://geronimo.apache.org/xmlns/j2ee/web/tomcat-2.0.1">
org.apache.geronimo.common.DeploymentException: Unable to deploy pit5-badns.war: Cannot handle web plan with namespace http://geronimo.apache.org/xmlns/j2ee/web/tomcat-2.0.1 -- expecting http://geronimo.apache.org/xml/ns/j2ee/web-2.0.1 or http://geronimo.apache.org/xml/ns/j2ee/web/tomcat-2.0.1
修正:报错原文把两个合法命名空间都列了,Tomcat 版服务器用 http://geronimo.apache.org/xml/ns/j2ee/web/tomcat-2.0.1(注意同样是 xml/ns)。
4.6 坑六:WAR 缺 dep:dependency 依赖声明
错误写法:geronimo-web.xml 的 environment 只有 moduleId、没有 dependencies。
org.apache.geronimo.common.DeploymentException: Unable to deploy pit6-nodep.war: Unable to resolve resource reference 'java:comp/env/jdbc/DemoDS' (Could not find resource 'jdbc/DemoDS'. Perhaps it has not yet been configured, or your application does not have a dependency declared for that resource module?
Search conducted in current module and dependencies:
[all: org.apache.geronimo.configs/tomcat7/3.0.1/car]
[all: org.apache.geronimo.configs/wink/3.0.1/car]
[all: org.apache.geronimo.configs/j2ee-corba-yoko/3.0.1/car]
[all: org.apache.geronimo.configs/axis//car]
[all: org.apache.geronimo.configs/axis2//car]
[all: org.apache.geronimo.configs/openjpa2/3.0.1/car]
[all: org.apache.geronimo.modules/geronimo-bval//jar]
[classes: org.apache.geronimo.configs/openejb//car]
)
Geronimo 只在「当前模块 + 已声明依赖」的范围内查找资源,连接池模块不在依赖链上就找不到 jdbc/DemoDS。修正:补 dep:dependency 指向 demo/demo-derby-pool/1.0/car(见 3.2 节)。
4.7 六坑速查表
| 坑 | 触发写法 | 报错关键字 | 修正 |
|---|---|---|---|
| 1 | plan 单独 deploy | no deployer is able to handle it | RAR+plan 联合部署 |
| 2 | connector 根命名空间 xmlns 变体 | document element namespace mismatch | 用 xml/ns/j2ee/connector-1.2 |
| 3 | 缺 workmanager | cvc-complex-type.2.4c | 补 gbean-link DefaultWorkManager |
| 4 | 连接属性放 resourceadapter-instance | cvc-complex-type.2.4b / XBM0A | 属性移入 connectiondefinition-instance |
| 5 | geronimo-web 根命名空间 xmlns 变体 | Cannot handle web plan with namespace | 用报错明示的两个 xml/ns 之一 |
| 6 | WAR 缺 dep:dependency | Unable to resolve resource reference | 补依赖连接池 car 模块 |
五、管理员口令与账号体系
5.1 属性 Realm 的两个文件
Geronimo 默认用属性文件 Realm 管理控制台与 deploy 工具的登录,两个文件:
var/security/users.properties:一行一个用户名=密码,密码支持明文或{Simple}密文;var/security/groups.properties:一行一个组名=用户1,用户2。
默认账号 system,默认口令 manager。实测文件形态(口令已改密为 q1w2e3r4 的状态):
system={Simple}rO0ABXNyABlqYXZheC5jcnlwdG8uU2VhbGVkT2JqZWN0PjY9psO3VHACAARbAA1lbmNvZGVkUGFyYW1zdAACW0JbABBlbmNyeXB0ZWRDb250ZW50cQB+AAFMAAlwYXJhbXNBbGd0ABJMamF2YS9sYW5nL1N0cmluZztMAAdzZWFsQWxncQB+AAJ4cHB1cgACW0Ks8xf4BghU4AIAAHhwAAAAEB99EdsvswE99QlYm7RBQtxwdAADQUVT
monitor={Simple}rO0ABXNyABlqYXZheC5jcnlwdG8uU2VhbGVkT2JqZWN0PjY9psO3VHACAARbAA1lbmNvZGVkUGFyYW1zdAACW0JbABBlbmNyeXB0ZWRDb250ZW50cQB+AAFMAAlwYXJhbXNBbGd0ABJMamF2YS9sYW5nL1N0cmluZztMAAdzZWFsQWxncQB+AAJ4cHB1cgACW0Ks8xf4BghU4AIAAHhwAAAAEB99EdsvswE99QlYm7RBQtxwdAADQUVT
admin=system
monitor=monitor
admin 组拥有管理权;monitor 组仅监控。
5.2 生成密文并改口令
用 deploy 的 encrypt 生成密文(命令与回显实测,详见第 4 篇 7.1 节):
./bin/deploy --offline encrypt q1w2e3r4
String to encrypt: q1w2e3r4
Offline encryption result:
{Simple}rO0ABXNyABlqYXZheC5jcnlwdG8uU2VhbGVkT2JqZWN0PjY9psO3VHACAARbAA1lbmNvZGVkUGFyYW1zdAACW0JbABBlbmNyeXB0ZWRDb250ZW50cQB+AAFMAAlwYXJhbXNBbGd0ABJMamF2YS9sYW5nL1N0cmluZztMAAdzZWFsQWxncQB+AAJ4cHB1cgACW0Ks8xf4BghU4AIAAHhwAAAAEB99EdsvswE99QlYm7RBQtxwdAADQUVT
把整行 {Simple}... 覆盖 users.properties 中对应用户的值,然后免重启验证:
./bin/deploy --user system --password q1w2e3r4 list-modules
Found 84 modules
5.3 明文条目同样合法
实测向 users.properties 追加明文行 system=manager 后,无需重启:
./bin/deploy --user system --password manager list-modules
Found 84 modules
即属性 Realm 每次登录都读文件,条目明文/密文混用均可,改动即时生效——临时找回口令很快,但生产环境务必用 5.2 节密文形态。
5.4 新增账号并授权 deploy 操作
实测流程:向 users.properties 追加(密文即 q1w2e3r4 的 encrypt 结果):
deployer={Simple}rO0ABXNyABlqYXZheC5jcnlwdG8uU2VhbGVkT2JqZWN0PjY9psO3VHACAARbAA1lbmNvZGVkUGFyYW1zdAACW0JbABBlbmNyeXB0ZWRDb250ZW50cQB+AAFMAAlwYXJhbXNBbGd0ABJMamF2YS9sYW5nL1N0cmluZztMAAdzZWFsQWxncQB+AAJ4cHB1cgACW0Ks8xf4BghU4AIAAHhwAAAAEB99EdsvswE99QlYm7RBQtxwdAADQUVT
向 groups.properties 的 admin 行追加:
admin=system,deployer
免重启验证新账号可执行部署工具命令:
./bin/deploy --user deployer --password q1w2e3r4 list-modules
Found 83 modules
5.5 控制台入口的认证行为
curl -sI --max-time 5 http://localhost:8080/console
HTTP/1.1 302 Found
Server: Apache-Coyote/1.1
Location: http://localhost:8080/console/
curl -sI --max-time 5 http://localhost:8080/console/
HTTP/1.1 403 Forbidden
Server: Apache-Coyote/1.1
Content-Type: text/html;charset=utf-8
无凭据的 curl 得到 403;浏览器访问 /console/ 会弹出表单登录页,输入管理员账号(如 system/manager)即可进入控制台。控制台里的 Applications → Deploy New 与命令行 deploy 工具能力等价,本文以命令行实测为准。
5.6 Login Failed 排障
凭据不符时 deploy 工具的实测输出(关键行):
org.apache.geronimo.common.DeploymentException: Login Failed
at org.apache.geronimo.deployment.cli.OnlineServerConnection.tryToConnect(OnlineServerConnection.java:126)
排查顺序:① users.properties 里该用户行是否存在、值是否与输入一致(密文/明文别混猜);② 该用户是否在 groups.properties 的 admin 组(部分管理操作要求 admin 角色);③ 服务器是否为改密前启动的老进程在缓存旧口令(属性 Realm 不缓存,通常无需重启,但改错文件路径会无效果)。
六、注意事项与常见问题
6.1 plan 里名字与 WAR 引用的对应关系
三处名字必须对上:plan 的 connectiondefinition-instance/name(jdbc/DemoDS)= WAR geronimo-web.xml 的 resource-ref/resource-link = web.xml 的 res-ref-name。任何一处改名都会复现坑六。
6.2 连接池模块停了会怎样
demo/demo-derby-pool/1.0/car 被 stop 后,依赖它的 WAR 请求会在 getConnection 处抛异常(404/500 视 stop 时机)。重启用 deploy start demo/demo-derby-pool/1.0/car 即可,数据不丢。
6.3 Derby 目录残留
服务器异常掉电可能在 var/derby 留下缺 service.properties 的残目录(坑 4.4 的 XBM0A 原文即此场景的变体)。处理:停服后删掉对应库名目录,重启后 CreateDatabase=true 会重建;应用数据需要先备份。
6.4 {Simple} 加密的边界
{Simple} 是可逆的轻量混淆,不是强加密;它防的是「直接读文件看到明文」,不防拿到服务器文件系统权限的攻击者。更高要求应限制服务器登录权限并按期轮换口令(轮换=重新 encrypt+覆盖 users.properties,免重启)。
6.5 凭据管理的最小权限实践
按 5.4 节模式为部署流水线单开账号(如 deployer),只在 admin 组保留必要的操作者;monitor 账号用于只读监控,避免把 system 高权账号写进 CI 配置。
七、参考链接
- TranQL 资源适配器(服务器内置):
$G/repository/org/tranql/tranql-connector-derby-embed-local/1.8/tranql-connector-derby-embed-local-1.8.rar - connector plan 官方 schema(注意其 targetNamespace 存在 xmlns 变体误导,命名空间以本文 4.2/4.5 报错原文为准):
$G/schema/geronimo-connector-1.2.xsd - 安全文件:
$G/var/security/users.properties、$G/var/security/groups.properties - Apache Geronimo 官方文档主页:
http://geronimo.apache.org/documentation.html - 同系列实操篇:《Apache Geronimo 3.0.1 常用命令与部署工具详解》(deploy 命令全解)、《Apache Geronimo 3.0.1 快速入门与集成示例》(WAR 部署主线)