分享
 
 
 

使用嵌入式 Tomcat 简化程序调试

王朝java/jsp·作者佚名  2006-01-09
窄屏简体版  字體: |||超大  

原文:http://www.blogcn.com/User8/flier_lu/blog/4740621.html

在开发基于 Tomcat 的 Web 程序时,一个比较头痛的问题就是如何将以接口分离的后台服务与前台页面进行联调。以 Tomcat 为中心的运行环境中虽然能够支持 IDE 直接进行跟踪调试,但配置麻烦、速度较慢且限制很多,总不如直接对后台程序进行调试来的方便。

一个较好的解决方法,是利用 Tomcat 的嵌入式版本,将 Tomcat 反过来嵌入到后台服务中,以后台服务为主进行调试。这样一来 Tomcat 从整体容器变为后台服务的一种,在不改变行为的前提下,能够自行定制调试环境。例如笔者开发的一个后台服务调试环境,支持基于命令行的简便移用的调试命令,直接对各种后台服务进行控制,并通过前台界面验证结果,大大减轻了整合时的调试难度。

虽然普通配置的 Tomcat 理论上也可以直接嵌入到后台程序,但推荐还是使用 Tomcat 定制的 Embeded 版本,这样集成度更高且性能较好。同时因为代码完全相同,不会存在调试环境内外的功能上的差异问题。

Tomcat 5.0.28 Embed tar.gz

在解压 Tomcat Embed 版本后,将其 lib 目录下所有 .jar 文件加入到 Java 项目的 classpath 中,就可以着手在 Java 程序中启动 Tomcat 了。与普通的 Tomcat 配置类似,其运行需要创建如下组织的结构:

以下内容为程序代码:

<Server>

<Service>

<Connector />

<Engine>

<Host>

<Context />

</Host>

</Engine>

</Service>

</Server>

只不过平时是配置 web.xml,而在嵌入版本中直接以程序方式完成。

首先是建立 Tomcat 服务器,并指定其运行目录,此目录最好与 Tomcat Embed 版本路径相同。

以下内容为程序代码:

Embedded tomcat = new Embedded();

tomcat.setCatalinaHome(path);

tomcat.addEngine(engine);

tomcat.setDebug(Logger.WARNING);

然后创建缺省 Engine 和 Host,并将 Host 加入到 Engine 中。这里的名字只是起到标记作用,但 Host 的路径最好与 tomcat 路径保持一致。同一 Engine 实际上是可以有多个虚拟 Host 的,对大型站点的自动测试可以将之分离进行。

以下内容为程序代码:

Engine engine = tomcat.createEngine();

engine.setName("EspServer"

;

Host host = tomcat.createHost("localhost", tomcat.getCatalinaHome() + "/webapps"

;

engine.addChild(host);

engine.setDefaultHost(host.getName());

对 Host 的内容填充,实际上就是具体 Web 应用程序的环境的建立过程。首先应该有一个缺省的 Context,在 URL 路径不匹配的时候会被使用。缺省 Context 的虚拟路径可以被设置为 "",内部实现时自动转换为 "/";而其物理路径可以直接使用 Tomcat 自带的 /webapps/ROOT 内容,或者使用自定义内容。

以下内容为程序代码:

Context ctxtRoot = tomcat.createContext("", host.getAppBase() + "/ROOT"

;

ctxtRoot.setPrivileged(true);

host.addChild(ctxtRoot);

值得注意的是这里设置 ROOT 为特权程序,其区别主要在于 Context 容器的 ClassLoader 等。具体细节有兴趣的朋友可以参考 Tomcat 中关于 classloading 的文档

以下内容为程序代码:

Bootstrap

|

System

|

Common

/ Catalina Shared

/ Webapp1 Webapp2 ...

而对用户自己的 WebApp 实际上并不限于相同目录,完全可以任意设置,使用与创建 ROOT 程序类似的方式即可。

最后需要创建合适的 Connector 接受 http/https 请求。推荐将 web 服务绑定在本地 loopback 地址上,限制只能本机访问。

以下内容为程序代码:

try

{

tomcat.addConnector(tomcat.createConnector(

InetAddress.getByName("127.0.0.1"

, 8080, false));

}

catch (UnknownHostException e)

{

System.err.println("Bind tomcat server to 127.0.0.1:8080 failed."

;

e.printStackTrace();

tomcat = null;

}

完整的嵌入式 Tomcat 创建代码示例如下:

以下内容为程序代码:

private Embedded createTomcat(String path)

{

Embedded tomcat = new Embedded();

tomcat.setCatalinaHome(path);

Engine engine = tomcat.createEngine();

engine.setName("EspServer"

;

Host host = tomcat.createHost("localhost", tomcat.getCatalinaHome() + "/webapps"

;

engine.addChild(host);

engine.setDefaultHost(host.getName());

Context ctxtRoot = tomcat.createContext("", host.getAppBase() + "/ROOT"

;

ctxtRoot.setPrivileged(true);

host.addChild(ctxtRoot);

String espPath = ConfigManager.getProperty("ESP_ROOTDIR"

;

if(espPath == null || !new File(espPath).exists())

{

espPath = host.getAppBase() + "/esp";

if(!new File(espPath).exists())

{

System.err.println("You should set ESP_ROOTDIR in esp.config."

;

return null;

}

}

Context ctxtEsp = tomcat.createContext("/esp", espPath);

host.addChild(ctxtEsp);

tomcat.addEngine(engine);

tomcat.setDebug(Logger.WARNING);

try

{

tomcat.addConnector(tomcat.createConnector(

InetAddress.getByName("127.0.0.1"

, 8080, false));

}

catch (UnknownHostException e)

{

System.err.println("Bind tomcat server to 127.0.0.1:8080 failed."

;

e.printStackTrace();

tomcat = null;

}

return tomcat;

}

然后就可以在合适的时候调用其 start/stop 方法启动或停止服务,感觉比标准配置的 tomcat 反映迅速许多。

此外可以通过一个辅助类的方法 ServerInfo.getServerInfo() 获取当前 Tomcat 版本信息用于显式状态

screen.width/2)this.width=screen.width/2" vspace=2 border=0

在此过程中有一些需要注意的细节问题。

1.运行此程序时需要使用 JDK 而非 JRE,因为 Tomcat 需要动态编译 JSP 页面,可能还需要手工把 JDK 的 /lib/tools.jar 加入到项目 classpath 中。

2.因为嵌入式版本 Tomcat 没有 common/lib 目录,如果碰到 JAXP 的 Provider 没有找到的 bug,可能需要直接将 xercesImpl.jar 等实现包复制到 JDK 的 /jre/lib/endorsed 目录下。

3.注意 classpath 中不要有其他版本 tomcat 的包,否则可能会出现冲突。

如果需要进一步了解相关信息,可以参考 Tomcat 自带 JavaDoc 文档,或者 O'Reilly 的 Embedding Tomcat Into Java Applications 一文。

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
2023年上半年GDP全球前十五强
 百态   2023-10-24
美众议院议长启动对拜登的弹劾调查
 百态   2023-09-13
上海、济南、武汉等多地出现不明坠落物
 探索   2023-09-06
印度或要将国名改为“巴拉特”
 百态   2023-09-06
男子为女友送行,买票不登机被捕
 百态   2023-08-20
手机地震预警功能怎么开?
 干货   2023-08-06
女子4年卖2套房花700多万做美容:不但没变美脸,面部还出现变形
 百态   2023-08-04
住户一楼被水淹 还冲来8头猪
 百态   2023-07-31
女子体内爬出大量瓜子状活虫
 百态   2023-07-25
地球连续35年收到神秘规律性信号,网友:不要回答!
 探索   2023-07-21
全球镓价格本周大涨27%
 探索   2023-07-09
钱都流向了那些不缺钱的人,苦都留给了能吃苦的人
 探索   2023-07-02
倩女手游刀客魅者强控制(强混乱强眩晕强睡眠)和对应控制抗性的关系
 百态   2020-08-20
美国5月9日最新疫情:美国确诊人数突破131万
 百态   2020-05-09
荷兰政府宣布将集体辞职
 干货   2020-04-30
倩女幽魂手游师徒任务情义春秋猜成语答案逍遥观:鹏程万里
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案神机营:射石饮羽
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案昆仑山:拔刀相助
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案天工阁:鬼斧神工
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案丝路古道:单枪匹马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:与虎谋皮
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:李代桃僵
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:指鹿为马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:小鸟依人
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:千金买邻
 干货   2019-11-12
 
推荐阅读
 
 
 
>>返回首頁<<
 
靜靜地坐在廢墟上,四周的荒凉一望無際,忽然覺得,淒涼也很美
© 2005- 王朝網路 版權所有