??xml version="1.0" encoding="utf-8" standalone="yes"?>
Jetty具备以下特点Q?/font>
。Jetty是最快的Servlet服务器之一
应用q泛
。商业项目有IBM Tivoli, Sonic MQ and Cisco SESM{?/font>
可到Jetty|站 http://jetty.mortbay.org/jetty/ 查看最C?/font>
Jetty按照功能可以分ؓ四个M主要的部?HttpServer,HttpContext,HttpHandler,HttpListener,详见如下cd:
<?1-1>
<?1-7 >
上图展示了一个request的处理过E?首先HttpListener监听到客L发来的请求创Z个HttpConnection实例(装?
q接l节,比如从Socketq接中获取的输入和输出?,
HttpConnection对象构徏q程中会创徏Jetty内部自定义的HttpRequest和HttpResponse对象,接着
HttpListener会调用这个HttpConnection实例的handleҎ(gu),
HttpConnection实例p用HttpRequest对象的read()Ҏ(gu)d信息,调用HttpServer的serviceҎ(gu)?
HttpRequest,HttpResponse为参ClHttpServer,HttpServer又将HttpRequest?
HttpResponse分发l相应的HttpCotext,HttpContext最后将HttpRequest和HttpResponse交给自n?
HttpHandler
处理,在这里HttpRequest,HttpResponse被再ơ封装ؓServletHttpRequest?
ServletHttpResponse,其实q两个类实现了我们所熟知的HttpServletRequest?
HttpServletResponse接口?/font>
1.HttpHandler:
SecurityHandler:提供基本的安全验?/font>
ForwardHandler:转发一个request到另一个url
HttpListener & HttpServer:
HttpListener是所有监听器cȝ接口,如图中的SocketListener(Z传统的Socket技?实C该接?Jetty
q有其它的实现该接口c?如SocketChannelListener(ZNIO技?cȝ,HttpListener职责主要是在服务器启动后监听
相应端口的来自客Lhq徏立连??1-1
中所C用HttpConnection装q接l节),监听器可在同个IP上开启多个端口ؓ同一个HttpServer
q行监听,所以HttpListener和HttpServer是多对一的关p?如下?
<?1-3 >
HttpContext & HttpHandler:
HttpContext相当于对应客Lh的URL或某个虚拟机, 其子cM包含若干个HttpHandler,
当接受到request(h)?HttpContext会依?按某个预定的ơ序)把request交给q些HttpHandler处理,直到q个
request被标C处理过为止,
需要注意的是这个request可能被多个HttpHandler处理Q但只能有一个HttpHandler能标C个request已被处理q?
<?1-5 >
另外Jetty对多|卡Q多个IP地址,不同的主机名Q的服务器也提供了很好的支持,每个HttpContext都有自n的HttpServer:
<?1-6 >
listener1.setHost(“www.app1.com?;//orListener1.setHost(“www.app2.com?
listener2.setPort(80);
HttpContext context1 = new HttpContext();
context1.setContextPath(??;
server1.addContext(context1);
本文通过囄要介l了Jetty整个体系架构和主要的lgcd服务器的启动执行q程,其实Jetty 通常被用来做为内嵌的Web
Server来用,一些常见的服务器YӞ如Apache Cocoon、JBoss
,JOnAs{都会采用Jetty作ؓWeb解決Ҏ(gu)Q另外由于Jetty在性能及稳定性要优于同类HTTP
Server的原因,Jetty已在国外已很行,鉴于q一?本文作者可以预在不久的将来Jetty同样也会在国内流行开来?/font>
本文档提供关于Tomcat的基信息.主要内容如下: Getting Started 独立的servlet容器 startup 在后台启动Tomcat.”tomcat start”命令的替换方式 shutdown 关闭Tomcat.”tomcat stop”命令的替换方式 在Unix下的步骤Q?/font> 如未指定,推测 TOMCAT_HOME 如未指定,推测 JAVA_HOME 讄CLASS_PATH包含: 1.${TOMCAT_HOME}/classes目录(如果存在) 2.${TOMCAT_HOME}/lib的一切内?/font> 3.${JAVA_HOME}/lib/tools.jar(此jar文g包含工具javac,我们需要javac处理jsp文g. 此Tomcatq程使用指向server.xml的\? 例如server.xml攄于etc/server_1.xmlq且用户意图在后台启动apache,?入如下命令行: bin/tomcat.sh start –f /etc/server_1.xml 在Win32下的步骤Q?? Tomcat的配|基于两个配|文? 1.server.xml - Tomcat的全局配置文g 2.web.xml - 在Tomcat中配|不同的关系环境 server.xml是Tomcat的主配置文g.完成两个目标: 1 提供Tomcatlg的初始配|? 2 说明Tomcat的结?含义,使得Tomcat通过实例化组件完成v动及构徏自n, 如在server.xml所指定?/font> 下表描述server.xmlU的重要元素: 元素及其描述 Server Logger ContextManager ContextInterceptor&RequestInterceptor Connector 1.句柄c?/font> 2.句柄监听的TCP/IP端口 3.句柄服务器端口的TCP/IP的backlog. E后我们在此文档中描述如何配置Connector. Context 1. Context攄的\?可以是与ContextManagerȝ录相关的路径. 2.U录调试信息的调试?/font> 3.
可重载的标志.开发Servlet?重蝲更改后的Servlet,q是一个非怾利的Ҏ(gu)?你可以调试或用Tomcat试C码而不用停止或重新启动
Tomcat.要打开重蝲,把reloadable设ؓ真即?q虽p旉但可所发生的变?更重要的?鉴于,在一个装载类对象装入一个新?
servlet?c装载触发器可能会掷Z些错?为避免这些问?你可以设|可重蝲为假,q将停止重蝲功能. 从另一个目录中启动Tomcat 作ؓ~省值将使用TOMCAT_HOME/conf/server.xml作ؓ配置文g.~省配置用TOMCT_HOME作ؓ关系环境的基. 使用 ?f/你的/目录/server.xml”选项你可改变q种情况,使用另一个服务器配置文g和设|关pȝ境管理器的目录属性你需要在ȝ录内讄以下几个文g: Ø 一?webapps/目录(如果你已生成) ?所有war文g奖杯界压倒此目录而且所有子目录作为关pȝ境添? Ø conf/目录 - 你可保存一个特D的web.xml文g和其他配|文?/font> Ø logs/ - 所有日志文件将代替TOMCAT_HOME/logs/U录到此目录?/font> Ø work/ - 关系环境的工作目?/font> 如server.xml中的ContextManager.home属性有兌,关联到到当前工作目? web。xml 关于web。xml和web目l构Q包括目录服务及配置Q的详细描述可在Servlet API Spec的第9Q?0Q?4章中扑ֈ?/font> ?
而有一个与Tomcat有关的小“特性“与web.xml有关。Tomcat可以让用户通过缺省的web.xml攑օconf目录中来定义所有关pȝ?
的web.xml的缺省?建立一个新的关pȝ境时,Tomcat使用~省的web.xml文g作ؓ基本讄和应用项目特定的web.xml(攑֜应用?
目的WEB-INF/web.xml文g)来覆盖这些缺省? 讄Tomcat与Apache Web 服务?/font> 服务?/font> 到现在ؓ?我们未讨Z为服务器扩展的Tomcat,只讨Z作ؓ独立q行的服务器.但有一些问题需要说? 1. 当处理静态页面时,Tomcat不如Apacheq? 2. Tomcat不象Apache一样可配置. 3. Tomcat不象Apache一样强? 4. 有很多网站已在某一特定web server上投入了很长旉,例如,使用CGI脚本/Server API模组/perl/php…我们不能假设这些遗留下来的东西都会被丢? Z以上原因,一个现实的|站使用一个Web服务?如Apache,为网站的静态页面请求提供服?q用Tomcat作ؓ一个Servlet/JSP插g. 我们不准备深入的讨论每个不同的配|?我们? 1. 늛Web服务器的基本行ؓ 2. 解释需要何U配|?/font> 3. 在Apache上的实例 载入servlet容器接口库ƈ初始化(处理h之前Q?/font> 当收C个请求时Q检查是否属于某ServletQ如是,则接口库接收此请求ƈ处理?/font> 另一斚wQ接口库需要知道他服务某U请求,通常是基于请求的URL的某U模式和此h导向何处?/font> 当用h要设|用虚拟主机的配置Ӟ事情会变得更加复杂,或者想多个开发者在一个服务器上进行开发但使用不同的Servlet容器的JVMs。以下我们将讨论q两个问题?/font> l 考虑到Tomcatq程是否可取得,我们仍需提供配置和Tomcat正在监听的TCP/IP L?端口受?/font> l 需要告知web服务器接口库的位|(因此我们可以在v始时装入Q?/font> l 需要设|接口内部信息如日志记录在何处和如何纪录,{等?/font> 所有此cM息必d现在web服务器配|里或被接口使用的私有配|文件中。下面将讲述如何在Apache中如何实现这些配|?/font> q一部分演示如何配置Apache与Tomcat一起工作;q试图解释深入到可能会用到的配置规范。在jserv 安装上可找到其他信息?
一?L
。Jetty可以处理上千个ƈ发连?
y嵌入
。Jetty的jar只有600多K
。可动态嵌入到应用E序Q适合开发web2.0{应?
本文通过对Jetty最新稳定版 Jetty5.1.5RC2 源码的研IӞ向读者展CJetty在设计方面用的不同设计理念, 希望对广大开发者在设计自己的系l时有所帮助?
二、HttpServer及配|?/font>
对于初次接触Jetty的h一定会对上图感到迷惑,其实在Jetty中HttpServer是一个服务器的核心控制类,
我们可以看到Q其它的lgc都是由该类扩展开来,HttpServer的作用就是在一pd的监听器cd处理器类之间搭v了一个桥?有效的控制着消息在系
l内的传?如下?
HttpServer职责是接受从HttpListener传递过来的request(h),HttpServer通过对request?
Host(L)或Path(路径)q行匚w,然后分发l相应的HttpContext(可以理解Z个web application)?/font>
q里举个例子Q假设我们现在要建立一个提供静态页面web服务,面内容在c:\root\?可以通过如此配置HttpServer:
HttpServer server = new HttpServer(); // 创徏一个新的HttpServer
SocketListener listener = new SocketListener(); // 创徏一个新监听?
listener.setPort(8080);// 讄监听端口?080
server.addListener(listener);// 监听类注册到server?
HttpContext context = new HttpContext(); // 创徏一个新HttpContext
context.setContextPath("/app/*"); // 讄讉K路径
context.setResourceBase("c:/root/"); // 讄静态资源\?
context.addHandler(new ResourceHandler()); // 个HttpContextd一个静态资源处理器
server.addContext(context); // 这个HttpContext注册到server?
server.start();// 最后启动这个server
当我们要建立一个提供动态页面web服务? 假设我们自己?web 应用攑֜Jetty目录下的webapps下ƈ打好包文件名为myapp.war, 可以通过如此配置HttpServer:
Server server = new Server(); // 创徏一个新的HttpServer
SocketListener listener = new SocketListener();// 创徏一个新监听?
listener.setPort(8080); // 讄监听端口?080
server.addListener(listener ); // 监听类注册到server?
server.addWebApplication("myapp","./webapps/myapp/"); // 这个web应用注册到这个Server?
server.start(); // 最后启动这个server
短短数行代码可创徏一个web服务器ƈ启动?q有点类g我们windows中的x即用的概?需要什么就d什?把这些类以HttpServer为核心组合在一P可以完成强大的功能?/font>
三、Jetty Server
1.上面我们探讨了HttpServer的启?读者一定还存在q样疑问,整个Jetty服务器是怎样启动的?
首先我们可以在图 1-1
看到左下角有一个Serverc?q个cd际上l承了HttpServer,当启动Jetty服务器时Q具体来_在Jetty根目录下命o行下如输?
java -jar start.jar etc/demo.xmlQ注意这里有一个配|文件demo.xml做ؓq行参数,q个参数也可以是其它的配|?
文g,也可是多个xml配置文gQ其实这个配|文件好比我们用struts时的struts-config.xml文gQ将q行Server需要用到的
lg写在里面Q比如上一节中HttpServer的配|需要的lgc都可以写在q个配置文g中?
2.我们自己部v到Jetty的webapps目录下的web application,Jetty如何q行我们自己的web application?
首先当我们按上述Ҏ(gu)启动Jetty
Server?׃调用Serverc里面的mainҎ(gu),q个入口Ҏ(gu)首先会构造一个Servercd?其实也就构造了一?
HttpServer),创徏实例q程中就会构造XmlConfigurationcȝ对象来读取参数配|文Ӟ之后再由q个配置文g产生?
XmlConfiguration对象来配|这个Server,配置q程其实是运用Java的反机制调用Server的方法ƈ传入配置文g中所写的参数
来向q个ServerdHttpListener,HttpContext,HttpHandler,web
application(对应我们自己部v的web应用)?
d我们自己的web
applicationq程中相应的׃d我们所熟知?WEB-INF/web.xml来创Z个WebApplicationContext(q个
cȝ承了HttpContext)的实?同时也会创徏WebApplicationContext自n的ServletHandler(实现?
HttpHandler接口),注意到ServletHandler中包含一lServletHolder指向实际的Servlet,譬如说我们在
web.xml文g中配|了两个Filter和一个Servlet,q里׃有三个ServletHolder,实际处理h?
ServeletHandler׃依次调用q三个ServletHolder传入request,response处理(实际最后交l这两个
Filter和Servlet处理),q样我们自己做好的一?
web应用挂载到q个Server上了,可以接受客户端相应的request(h)?
四、运行原?请参考如下时序图)
五、高U性能
该接口的实现cȝ于处理HttpContext分发q来的reqeust,不同的实现类的有不同的处理功?q里介绍几常用的HttpHandler实现c?
ReourceHandler:用于处理静态内?如以扩展名ؓ.html的文?
ServletHandler:用于request交由具体的Servletc进行处?
2.当你在看?1-2
时候会注意到HttpServer和HttpListener,HttpServer与HttpContextQHttpContext?
HttpHandler存在一对多的关p?下面׃l一下它们之间的q种关系如何通过E序来配|?
配置代码Q?/font>
HttpServer server = new HttpServer();
HttpListenrer listener1 = new SocketChanneListener();
Listener1.setPort(8080);
HttpListenrer listener1 = new SocketListener();
Listener1.setPort(8443);
server.addListener(listener1);
server.addListener(listener2);
一个典型的HttpContext有用于安全处理、静态资源处理及ServletcȝHttpHandler,如下?
配置代码Q?/font>
HttpContext context = new HttpContext();
context.setContextPath(?myapp/*?;
HttpHandler securitHandler = new SecurityHandler();
HttpHandler resourceHandler = new ResourceHandler();
HttpHandler servletHandler = new ServletHandler();
context.addHandler(securitHandler);
context.addHandler(resourceHandler);
context.addHandler(servletHandler);
HttpServer & HttpContext:
一般的HTTP服务器Y件可以同时处理多个web application,同样一个HttpServer可以包含多个HttpContext,如下囑֏以通过同一个端口的监听cL映射多个HttpContext:
配置代码Q?/font>
HttpServer server = new HttpServer();
HttpContext context1 = new HttpContext();
context1.setContextPath(?app1/*?;
HttpContext context2 = new HttpContext();
context2.setContextPath(?app2/*?;
server.addContext(context1);
HttpServer & HttpLister & HttpContext:
配置代码Q?/font>
HttpServer server1 = new HttpServer();
SocketListener listener1 = new SocketListener();
server1.addListener(listener1);
3.Jetty寚wq发的支?
如果多用戯求服务就会涉及到多线E的理Q如?
1-8,Jetty中主要由ThreadPool负责理多线E,注意其中Pool.PondLife是Pool的一个内部接?
ThreadPool.PoolThread是ThreadPool的一个内部线E类,我们看到Pool.PondLife和Pool存在一个聚集的?
p,实际上Pool对象中存攑֜是一个个ThreadPool.PoolThreadU程对象Q当有新用户q接上ServerӞThreadPool?
从Pool中取一个空闲的U程为当前用戯接服务?
六、小l?
附:
作者联pL式:陈应?dycyg@yahoo.com 熊红?eastbear@126.com
]]>
你所需要做的就是:按照你的需求配|TomcatQ只要你正确配置QTomcat一般都能适合你的要求。下面是一pd关于Tomcat的配|技巧,q些技巧源自于我的书:《Tomcat权威指南》,希望对你有所帮助。—?Jason Brittain
1Q?配置pȝ理QAdmin Web ApplicationQ?/b>
大多数商业化的J2EE服务器都提供一个功能强大的理界面Q且大都采用易于理解的Web应用界面。Tomcat按照自己的方式,同样提供一个成熟的理
工具Qƈ且丝毫不逊于那些商业化的竞争Ҏ(gu)。Tomcat的Admin Web
Application最初在4.1版本时出玎ͼ当时的功能包括管理context、data
source、user和group{。当然也可以理像初始化参数Quser、group、role的多U数据库理{。在后箋的版本中Q这些功能将?
到很大的扩展Q但现有的功能已l非常实用了?br>
Admin Web Application被定义在自动部v文gQCATALINA_BASE/webapps/admin.xml ?br>
Q译者注QCATALINA_BASE即tomcat安装目录下的server目录Q?br>
你必ȝ辑这个文Ӟ以确定Context中的docBase参数是绝对\径。也是_
CATALINA_BASE/webapps/admin.xml
的\径是l对路径。作为另外一U选择Q你也可以删除这个自动部|文Ӟ而在server.xml文g中徏立一个Admin Web
Application的contextQ效果是一L。你不能理Admin Web
Applicationq个应用Q换而言之,除了删除CATALINA_BASE/webapps/admin.xml Q你可能什么都做不了?br>
如果你用UserDatabaseRealmQ默认)Q你需要添加一个user以及一个role到CATALINA_BASE/conf/tomcat-users.xml 文g中。你~辑q个文gQ添加一个名叫“admin”的role 到该文g中,如下Q?br>
<role name="admin"/>
你同样需要有一个用Pq且q个用户的角色是“admin”。象存在的用户那Pd一个用P改变密码使其更加安全Q:
<user name="admin" password="deep_dark_secret" roles="admin"/>
当你完成q些步骤后,请重新启动TomcatQ访问http://localhost:8080/adminQ你看C个登录界面。Admin
Web Application采用Z容器理的安全机Ӟq用了Jakarta
Struts框架。一旦你作ؓ“admin”角色的用户d理界面Q你能够用这个管理界面配|Tomcat?br>
2Q配|应用管理(Manager Web ApplicationQ?/b>
Manager Web Application让你通过一个比Admin Web Application更ؓ单的用户界面Q执行一些简单的Web应用d?br>
Manager Web Application被被定义在一个自动部|文件中Q?br>
CATALINA_BASE/webapps/manager.xml ?br>
你必ȝ辑这个文Ӟ以确保context的docBase参数是绝对\径,也就是说CATALINA_HOME/server/webapps/manager的绝对\径?br>
Q译者注QCATALINA_HOME即tomcat安装目录Q?br>
如果你用的是UserDatabaseRealmQ那么你需要添加一个角色和一个用户到CATALINA_BASE/conf/tomcat-users.xml文g中。接下来Q编辑这个文Ӟd一个名为“manager”的角色到该文g中:
<role name=”manager?gt;
你同样需要有一个角色ؓ“manager”的用户。像已经存在的用户那Pd一个新用户Q改变密码其更加安全)Q?br>
<user name="manager" password="deep_dark_secret" roles="manager"/>
然后重新启动TomcatQ访问http://localhost/manager/listQ将看到一个很朴素的文本型理界面Q或者访问http:
//localhost/manager/html/listQ将看到一个HMTL的管理界面。不是哪种方式都说明你的Manager Web
Application现在已经启动了?br>
Manager
application让你可以在没有系l管理特权的基础上,安装新的Web应用Q以用于试。如果我们有一个新的web应用位于
/home/user/hello下在Qƈ且想把它安装?
/hello下,Z试q个应用Q我们可以这么做Q在W一个文件框中输入?hello”(作ؓ讉K时的pathQ,在第二个文本框中输入“file:
/home/user/hello”(作ؓConfig URLQ?br>
Manager
applicationq允怽停止、重新启动、移除以及重新部|一个web应用。停止一个应用其无法被讉KQ当有用户尝试访问这个被停止的应用时Q将
看到一?03的错误——?03 - This application is not currently available”?br>
U除一个web应用Q只是指从Tomcat的运行拷贝中删除了该应用Q如果你重新启动TomcatQ被删除的应用将再次出现Q也是_U除q不是指从硬盘上删除Q?br>
3Q部|一个web应用
有两个办法可以在pȝ中部|web服务?br>
1> 拯你的WAR文g或者你的web应用文g夹(包括该web的所有内容)?CATALINA_BASE/webapps目录下?br>
2> Z的web服务建立一个只包括context内容的XML片断文gQƈ把该文g攑ֈ$CATALINA_BASE/webapps目录下。这个web应用本n可以存储在硬盘上的Q何地斏V?br>
如果你有一个WAR文gQ你若想部v它,则只需要把该文件简单的拯到CATALINA_BASE/webapps目录下即可,文g必须以?war”作
为扩展名。一旦Tomcat监听到这个文Ӟ它将Q缺省的Q解开该文件包作ؓ一个子目录Qƈ以WAR文g的文件名作ؓ子目录的名字。接下来QTomcat
在内存中徏立一个contextQ就好象你在server.xml文g里徏立一栗当Ӟ其他必需的内容,从server.xml中的
DefaultContext获得?br>
部vweb应用的另一U方式是写一个Context
XML片断文gQ然后把该文件拷贝到CATALINA_BASE/webapps目录下。一个Context片断q一个完整的XML文gQ而只是一?
context元素Q以及对该应用的相应描述。这U片断文件就像是从server.xml中切取出来的context元素一P所以这U片断被命名?
“context片断”?br>
举个例子Q如果我们想部v一个名叫MyWebApp.war的应用,该应用用realm作ؓ讉K控制方式Q我们可以用下面这个片断:
<!--
Context fragment for deploying MyWebApp.war
-->
<Context path="/demo" docBase="webapps/MyWebApp.war"
debug="0" privileged="true">
<Realm className="org.apache.catalina.realm.UserDatabaseRealm"
resourceName="UserDatabase"/>
</Context>
把该片断命名为“MyWebApp.xml”,然后拯到CATALINA_BASE/webapps目录下?br>
q种context片断提供了一U便利的Ҏ(gu)来部|web应用Q你不需要编辑server.xmlQ除非你x变缺省的部vҎ(gu),安装一个新的web应用时不需要重启动Tomcat?br>
4Q配|虚拟主机(Virtual HostsQ?/b>
关于server.xml中“Host”这个元素,只有在你讄虚拟L的才需要修攏V虚拟主机是一U在一个web服务器上服务多个域名的机ӞҎ(gu)个域
名而言Q都好象独n了整个主机。实际上Q大多数的小型商务网站都是采用虚拟主机实现的Q这主要是因拟主直接q接到Internetq提供相应的?
宽,以保障合理的讉K响应速度Q另外虚拟主能提供一个稳定的固定IP?br>
Z名字的虚拟主机可以被建立在Q何web服务器上Q徏立的Ҏ(gu)是通过在域名服务器QDNSQ上建立IP地址的别名,q且告诉web服务器把d不同?
名的h分发到相应的|页目录。因文章主要是讲TomcatQ我们不准备介绍在各U操作系l上讄DNS的方法,如果你在q方面需要帮助,请参?
《DNS and Bind》一书,作者是Paul Albitz and Cricket Liu
(O'Reilly)。ؓ了示范方便,我将使用一个静态的L文gQ因是测试别名最单的Ҏ(gu)?br>
在Tomcat中用虚拟主机,你需要设|DNS或主机数据。ؓ了测试,为本地IP讄一个IP别名p够了Q接下来Q你需要在server.xml中添加几行内容,如下Q?br>
<Server port="8005" shutdown="SHUTDOWN" debug="0">
<Service name="Tomcat-Standalone">
<Connector className="org.apache.coyote.tomcat4.CoyoteConnector"
port="8080" minProcessors="5" maxProcessors="75"
enableLookups="true" redirectPort="8443"/>
<Connector className="org.apache.coyote.tomcat4.CoyoteConnector"
port="8443" minProcessors="5" maxProcessors="75"
acceptCount="10" debug="0" scheme="https" secure="true"/>
<Factory className="org.apache.coyote.tomcat4.CoyoteServerSocketFactory"
clientAuth="false" protocol="TLS" />
</Connector>
<Engine name="Standalone" defaultHost="localhost" debug="0">
<!-- This Host is the default Host -->
<Host name="localhost" debug="0" appBase="webapps"
unpackWARs="true" autoDeploy="true">
<Context path="" docBase="ROOT" debug="0"/>
<Context path="/orders" docBase="/home/ian/orders" debug="0"
reloadable="true" crossContext="true">
</Context>
</Host>
<!-- This Host is the first "Virtual Host": www.example.com -->
<Host name="www.example.com" appBase="/home/example/webapp">
<Context path="" docBase="."/>
</Host>
</Engine>
</Service>
</Server>
Tomcat的server.xml文gQ在初始状态下Q只包括一个虚拟主机,但是它容易被扩充到支持多个虚拟主机。在前面的例子中展示的是一个简单的
server.xml版本Q其中粗体部分就是用于添加一个虚拟主机。每一个Host元素必须包括一个或多个context元素Q所包含的context?
素中必须有一个是默认的contextQ这个默认的context的显C\径应该ؓI(例如Qpath=””)?br>
5Q配|基验证QBasic AuthenticationQ?/b>
容器理验证Ҏ(gu)控制着当用戯问受保护的web应用资源Ӟ如何q行用户的n份鉴别。当一个web应用使用了Basic
AuthenticationQBASIC参数在web.xml文g中auto-method元素中设|)Q而有用户讉K受保护的web应用Ӟ
Tomcat通过HTTP Basic
Authentication方式Q弹Z个对话框Q要求用戯入用户名和密码。在q种验证Ҏ(gu)中,所有密码将被以64位的~码方式在网l上传输?br>
注意Q用Basic
Authentication通过被认为是不安全的Q因为它没有强健的加密方法,除非在客L和服务器端都使用HTTPS或者其他密码加密码方式Q比如,
在一个虚拟私人网l中Q。若没有额外的加密方法,|络理员将能够截获Q或滥用Q用L密码。但是,如果你是刚开始用TomcatQ或者你惛_你的
web应用中测试一下基于容器的安全理QBasic
Authenticationq是非常易于讄和用的。只需要添?lt;security-constraint>?lt;login-
config>两个元素C的web应用的web.xml文g中,q且在CATALINA_BASE/conf/tomcat-users.xml
文g中添加适当?lt;role>?lt;user>卛_Q然后重新启动Tomcat?br>
下面例子中的web.xml摘自一个俱乐部会员|站pȝQ该pȝ中只有member目录被保护v来,q用Basic Authenticationq行w䆾验证。请注意Q这U方式将有效的代替Apache web服务器中?htaccess文g?br>
<!--
Define the Members-only area, by defining
a "Security Constraint" on this Application, and
mapping it to the subdirectory (URL) that we want
to restrict.
-->
<security-constraint>
<web-resource-collection>
<web-resource-name>
Entire Application
</web-resource-name>
<url-pattern>/members/*</url-pattern>
</web-resource-collection>
<auth-constraint>
<role-name>member</role-name>
</auth-constraint>
</security-constraint>
<!-- Define the Login Configuration for this Application -->
<login-config>
<auth-method>BASIC</auth-method>
<realm-name>My Club Members-only Area</realm-name>
</login-config>
6Q配|单点登录(Single Sign-OnQ?/b>
一旦你讄了realm和验证的Ҏ(gu)Q你需要进行实际的用户d处理。一般说来,对用戯言dpȝ是一件很ȝ的事情,你必d量减用L录验证的
ơ数。作为缺省的情况Q当用户W一ơ请求受保护的资源时Q每一个web应用都会要求用户d。如果你q行了多个web应用Qƈ且每个应用都需要进行单独的
用户验证Q那q看h有点像你在与你的用h斗。用户们不知道怎样才能把多个分ȝ应用整合成一个单独的pȝQ所有他们也׃知道他们需要访问多个?
同的应用Q只是很qhQؓ什么总要不停的登录?br>
Tomcat 4的“single sign-on”特性允许用户在讉K同一虚拟L下所有web应用Ӟ只需d一ơ。ؓ了用这个功能,你只需要在Host上添加一个SingleSignOn Valve元素卛_Q如下所C:
<Valve className="org.apache.catalina.authenticator.SingleSignOn"
debug="0"/>
在Tomcat初始安装后,server.xml的注释里面包括SingleSignOn Valve配置的例子,你只需要去掉注释,卛_使用。那么,M用户只要dq一个应用,则对于同一虚拟L下的所有应用同h效?br>
使用single sign-on valve有一些重要的限制Q?br>
1> value必须被配|和嵌套在相同的Host元素里,q且所有需要进行单炚w证的web应用Q必通过context元素定义Q都位于该Host下?br>
2> 包括׃n用户信息的realm必须被设|在同一UHost中或者嵌套之外?br>
3> 不能被context中的realm覆盖?br>
4>
使用单点d的web应用最好用一个Tomcat的内|的验证方式Q被定义在web.xml中的<auth-method>中)Q这比自?
义的验证方式强,Tomcat内置的的验证方式包括basic、digest、form和client-cert?br>
5>
如果你用单点登录,q希望集成一个第三方的web应用C的网站中来,q且q个新的web应用使用它自q验证方式Q而不使用容器理安全Q那你基本上
没招了。你的用hơ登录原来所有应用时需要登录一ơ,q且在请求新的第三方应用时还得再d一ơ。当Ӟ如果你拥有这个第三方web应用的源码,而你
又是一个程序员Q你可以修改它,但那恐怕也不容易做?br>
6> 单点d需要用cookies?br>
7Q配|用户定制目录(Customized User DirectoresQ?/b>
一些站点允怸别用户在服务器上发布|页。例如,一所大学的学院可能想l每一位学生一个公共区域,或者是一个ISP希望l一些webI间l他的客P但这又不是虚拟主机。在q种情况下,一个典型的Ҏ(gu)是在用户名前面加一个特D字W(~Q,作ؓ每位用户的网站,比如Q?br>
http://www.cs.myuniversity.edu/~username
http://members.mybigisp.com/~username
Tomcat提供两种Ҏ(gu)在主Z映射q些个h|站Q主要用一对特D的Listener元素。Listener的className属性应该是
org.apache.catalina.startup.UserConfigQuserClass属性应该是几个映射cM一。如果你的系l是
UnixQ它?yu)有一个标准的/etc/passwd文gQ该文g中的帐号能够被运行中的Tomcat很容易的dQ该文g指定了用Lȝ录,使用
PasswdUserDatabase 映射cR?br>
<Listener className="org.apache.catalina.startup.UserConfig"
directoryName="public_html"
userClass="org.apache.catalina.startup.PasswdUserDatabase"/>
web文g需要放|在?home/users/ian/public_html 或?/users/jbrittain/public_html一L目录下面。当然你也可以改变public_html 到其他Q何子目录下?br>
实际上,q个用户目录Ҏ(gu)不一定需要位于用户主目录下里面。如果你没有一个密码文Ӟ但你又想把一个用户名映射到公q?home一L录的子目录里面,则可以用HomesUserDatabasecR?br>
<Listener className="org.apache.catalina.startup.UserConfig"
directoryName="public_html" homeBase="/home"
userClass="org.apache.catalina.startup.HomesUserDatabase"/>
q样一来,web文g可以位于像/home/ian/public_html 或?/home/jasonb/public_html一L目录下。这UŞ式对Windows而言更加有利Q你可以使用一个像c:\homeq样的目录?br>
q些Listener元素Q如果出玎ͼ则必dHost元素里面Q而不能在context元素里面Q因为它们都用应用于Host本n?br>
8Q在Tomcat中用CGI脚本
Tomcat主要是作为Servlet/JSP容器Q但它也有许多传lweb服务器的性能。支持通用|关接口QCommon Gateway
InterfaceQ即CGIQ就是其中之一QCGI提供一l方法在响应览器请求时q行一些扩展程序。CGI之所以被UCؓ通用Q是因ؓ它能在大多数E序
或脚本中被调用,包括QPerlQPythonQawkQUnix shell
scripting{,甚至包括Java。当Ӟ你大概不会把一个Java应用E序当作CGI来运行,毕竟q样太过原始。一般而言Q开发Servlet?
要比CGIh更好的效率,因ؓ当用LM个链接或一个按钮时Q你不需要从操作pȝ层开始进行处理?br>
Tomcat包括一个可选的CGI ServletQ允怽q行遗留下来的CGI脚本?br>
Z使Tomcat能够q行CGIQ你必须做如下几件事Q?br>
1. 把servlets-cgi.renametojar Q在CATALINA_HOME/server/lib/目录下)改名为servlets-cgi.jar。处理CGI的servlet应该位于Tomcat的CLASSPATH下?br>
2. 在Tomcat的CATALINA_BASE/conf/web.xml 文g中,把关?lt;servlet-name> CGI的那D늚注释LQ默认情况下Q该D位于第241行)?br>
3. 同样Q在Tomcat的CATALINA_BASE/conf/web.xml文g中,把关于对CGIq行映射的那D늚注释LQ默认情况下Q该D位于第299行)。注意,q段内容指定了HTML链接到CGI脚本的访问方式?br>
4. 你可以把CGI脚本攄在WEB-INF/cgi
目录下(注意QWEB-INF是一个安全的地方Q你可以把一些不惌用户看见或基于安全考虑不想暴露的文件放在此处)Q或者你也可以把CGI脚本攄?
context下的其他目录下,qؓCGI Servlet调整cgiPathPrefix初始化参数。这指定的CGI
Servlet的实际位|,且不能与上一步指定的URL重名?br>
5. 重新启动TomcatQ你的CGI可以运行了?br>
在Tomcat中,CGIE序~省攄在WEB-INF/cgi目录下,正如前面所提示的那PWEB-INF目录受保护的Q通过客户端的览器无法窥?
到其中内容,所以对于放|含有密码或其他敏感信息的CGI脚本而言Q这是一个非常好的地斏Vؓ了兼容其他服务器Q尽你也可以把CGI脚本保存在传l的
/cgi-bin目录Q但要知道,在这些目录中的文件有可能被网上好奇的冲浪者看到。另外,在Unix中,L定运行Tomcat的用h执行CGI脚本
的权限?br>
9Q改变Tomcat中的JSP~译器(JSP CompilerQ?/b>
在Tomcat
4.1Q或更高版本Q大概)QJSP的编译由包含在Tomcat里面的AntE序控制器直接执行。这听v来有一点点奇怪,但这正是Ant有意Z的一?
分,有一个API文档指导开发者在没有启动一个新的JVM的情况下Q用Ant。这是用Antq行Java开发的一大优ѝ另外,q也意味着你现在能?
在Ant中用Q何javac支持的编译方式,q里有一个关于Apache Ant使用手册的javac
page列表。用v来是Ҏ(gu)的,因ؓ你只需要在<init-param>
元素中定义一个名字叫“compiler”,q且在value中有一个支持编译的~译器名字,CZ如下Q?br>
<servlet>
<servlet-name>jsp</servlet-name>
<servlet-class>
org.apache.jasper.servlet.JspServlet
</servlet-class>
<init-param>
<param-name>logVerbosityLevel</param-name>
<param-value>WARNING</param-value>
</init-param>
<init-param>
<param-name>compiler</param-name>
<param-value>jikes</param-value>
</init-param>
<load-on-startup>3</load-on-startup>
</servlet>
当然Q给出的~译器必dl安装在你的pȝ中,q且CLASSPATH可能需要设|,那处决于你选择的是何种~译器?br>
10Q限制特定主问(Restricting Access to Specific HostsQ?/b>
有时Q你可能想限制对Tomcat
web应用的访问,比如Q你希望只有你指定的L或IP地址可以讉K你的应用。这样一来,只有那些指定的的客L可以讉K服务的内容了。ؓ了实现这U效
果,Tomcat提供了两个参C你配|:RemoteHostValve 和RemoteAddrValve?br>
通过配置q两个参敎ͼ可以让你qo来自h的主机或IP地址Qƈ允许或拒l哪些主?IP。与之类似的Q在Apache的httpd文g里有Ҏ(gu)个目录的允许/拒绝指定?br>
例如你可以把Admin Web application讄成只允许本地讉KQ设|如下:
<Context path="/path/to/secret_files" ...>
<Valve className="org.apache.catalina.valves.RemoteAddrValve"
allow="127.0.0.1" deny=""/>
</Context>
如果没有l出允许L的指定,那么与拒l主机匹配的L׃被拒l,除此之外的都是允许的。与之类|如果没有l出拒绝L的指定,那么与允怸机匹配的L׃被允许,除此之外的都是拒l的?/font>
]]>
Tomcat二进制版本安?br>与Tomcat相关的脚本的主要内容
与server.xml相关的主要内?Tomcat的主要配|文?br>如何讄Tomcat与宿主web服务器一起工作的说明
如何应用Tomcat配置一个现实中的web站点
希望此文档以新用户可以开始用Tomcat.如找不到某方面的内容?按以下顺?
查找Tomcat faq
查找Tomcat包清?br>向Tomcat用户邮g列表发出问题
如此疑问的答案不存在,我们鼓励把对疑问的解{放入Tomcat faq或此文档.如对此文档有意见或徏?请发送到Tomcat的邮件列?
Tomcat是一个带有jsp环境的servlet容器.servlet容器是一个根据用L行ؓ可以理和激zservlet的运行时的shell.
_略地可以将servlet容器分ؓ如下几类:
内置有web服务器的一部分.指当使用ZJava的web服务器的情Ş,例如servlet容器是JavaWebServer的一个部? 独立的servlet容器是Tomcat的默认模?
大多数的web服务器ƈ非基于Java,因此,我们可以得出如下两种容器的模?
q程内的servlet容器
servlet
容器作ؓweb服务器的插g和Java容器的实?Web服务器插件在内部地址I间打开一个JVM(java virtual
machine)使Java容器得以在内部运?如有某个需要调用servlet的请?,插g取得对此请求的控制q将他传?使用JNI)lJava
容器.q程内容器对于多U程,单进E的服务器非常合适ƈ且提供很好的q行速度,但~性有所不.
q程外的servlet容器
servlet
容器q行于web服务器之外的地址I间且作为web服务器的插g和Java容器的实现的l合.web服务器插件和Java容器
JVM使用IPC机制(通常是TCP/IP)q行通讯.当一个调用servlet的请求到达时,插g取得对此请求的控制q将其传?使用IPC{?l?
Java容器,q程外容器的反应旉或进E外容器引擎不如q程内容?但进E外容器引擎在许多其他可比的范围内更?伸羃?E_性等).
Tomcat既可作ؓ独立的容?主要是用于开发与调试)又可作ؓ对现有服务器的附?当前支持Apache,IIS和Netscape服务?.即Q何时候配|Tomcat你都必须军_如何应用?如选择W二或第三种模式,你还需要安装一个web服务器接?
Tomcat与Jserv有何区别?Tomcat是Jserv?
q是个常见的误解.Jserv是Servlet API2.0兼容q与Apache一起用的容器.Tomcat是一个完全重写的q与Servlet API2.2和JSP1.1兼容的容?
Tomcat使用了一些ؓJserv而写的代?特别是Jserv的Apache接口,但这是唯一的相同之?
怎样安装Tomcat的二q制版本?
非常?只需:
下蝲 zip/tar.gz M压羃文g,从http://jakarta.apche.org/download/binindex.html?
解压~此文g到某目录(?foo).会生成一子目?名ؓ”tomcat?
转换到”tomcat”目录设|一新的环境变量(TOMCAT_HOME)指向你安装的tomcat的目?br>WIN32q_,键入:
“set TOMCAT_HOME=foo\tomcat?br>Unixq_:
如是bash/sh环境, 键入:”TOMCAT_HOME=foo/tomcat;export TOMCAT_HOME?br>如是tcsh环境, 键入:”setenv TOMCAT_HOME foo/tomcat?br>讄环境变量JAVA_HOME指向你JDK的目?然后dJAVA解释器到你的PATH环境变量.
好了!现在可以q行TOMCATq作Z个独立的Servlet容器(模式一)
启动与关闭Tomcat
使用”bin”目录中的脚本启动与关闭Tomcat.
启动:
uinx:bin/startup.sh
win32:bin\startup
关闭:
unix:bin/shutdown.sh
win32:bin\shutdown
Tomcat目录l构
假设你已Tomcat解压,你已得到下列目录l构:
目录?-描述
bin
包含启动/关闭脚本
conf
包含不同的配|文?
包括 server.xml(Tomcat的主要配|文?和ؓ不同的Tomcat配置的web应用讄~省值的文gweb.xml
doc
包含各种Tomcat文档
lib
包含Tomcat使用的jar文g.unixq_此目录下的Q何文仉被加到Tomcat的classpath?
logs
Tomcat摆放日志文g的地?
src
ServletAPI源文?先别高兴,q些只有些必dServlet容器内实现的I接口和抽象c?
webapps
包含web目CZ
此外你可以Tomcat会创建如下目?
work
Tomcat自动生成,攄Tomcatq行时的临时文g(如编译后的JSP文g).如在Tomcatq行时删除此目录.JSP面不能运?
classes
你可以创建此目录来添加一些附加的cdc\径中.M你加到此目录中的c都可在Tomcat的类路径中找到自w?
Tomcat的脚?br>Tomcat是一个JavaE序,因此在设|好几个环境变量后即可用命o行的方式q行.然而设|Tomcat使用的每个环境变量和如下的命令行参数乏味且易?因此,Tomcat开发组提供了一些脚本启动和关闭Tomcat变得L.
注意:q些脚本仅仅是个便利的方法去启动和关闭Tomcat.你可修改他们来定制CLASSPATH,环境变量如PATH,LD_LIBRARY_PATH,{等,只要是生成一个正的命o行即?
q些脚本是什么呢?下表列出对一般用h重要的脚?
tomcat
主脚?讄合适的环境变量,包括CLASSPATH,TOMCAT_HOME和JAVA_HOME和用适合的命令行参数启动Tomcat
对用h重要的脚本是tomcat(tomcat.bat/tomcat.sh).其他Tomcat相关的脚本作Z个简单的面向单Q务的指向Tomcat脚本(讄不同的命令行参数{?的入?
仔细考察tomcat.bat/tomcat.sh,它按以下步骤q行:
q?
行带有设定Java环境变量的命令行参数的java命o,调入tomcat.home,?
org.apache.tomcat.startup.Tomcat
作ؓ启始c?同时也传递命令行参数到org.apache.tomcat.startup.Tomcat ,例如:
执行start/stop/run {的操作
由此可见,win32版的tomcat.bat与Unix版的几乎一?其在它不推TOMCAT_HOME和JAVA_HOME的?q且不将所有的jar文g攑օc\径中.
Tomcat的配|文?/font>
q一部分讲q如何用这些文?我们不会包含web.xml的内部机?q些内部机制深入CServlet API的细?因此,我们讨论涵盖servler.xml内容及web.xml在Tomcat关系环境中的用法.
server.xml
server.xml文g中最重要的元?Server定义了一个Tomcat服务?一般你不用对他担心太多.Server元素能包含Logger和ContextManager元素cd
?
元素定义一个Logger对象,每个Logger都有一个名字去标识,也有一个纪录Logger的输出和冗余U别(描述此日志?和包含日志文件的?
?通常有servlet的Logger(ServletContext.log()?,JSP和Tomcatq行时的Logger.
ContextManager说明一套ContextInterceptor, RequestInterceptor , Context和他们的Connectors的配|及l构.ContextManager有几个随同提供的Ҏ(gu)?
1. 用来U录调试信息的调试?
2. webapps/,conf/,logs/和所有已定义的环境的基本位置.用来使Tomcat可以在TOMCAT_HOME外的其他目录启动.
3. 工作目录的名?/font>
q?
些侦听器(interceptors)侦听具体发生在ContextManager中的事g.例如,ContextInterceptor侦听
Tomcat的启动及l止事g,RequestInterceptor监视在它服务q程中用戯求需要通过的不同阶D?Tomcat的管理员不必知道太多
关于侦听器的知识;另外,开发者应该知道这是如何在Tomcat中实C个”全局”型的操?例如安全性及每个h日志)
Connector表示一个到用户的联?不管是通过web服务器或直接到用h览器(在一个独立配|中).Connector负责理Tomcat的工作线E和 ??q接C同用L端口?h/响应.Connector的配|包含如下信?
每个Context提供一个指向你攄你Web目的Tomcat的下属目录。每个Context包含如下配置Q?/font>
Web 服务器操?/font>
单说来,web服务器L{待来自客户端的HTTPh。当h到达Ӟ服务器会提供一切必要的内容来满xh。加入一个Servlet容器某种E度上会改变此行为。但服务器仍需处理如下因素Q?/font>
必需q行的配|?/font>
应该考虑的是最明显的配|是servlet URLh对servlet容器中的servleth表示的责仅R很明显Q你必须知道传递什么到Servlet容器。我们仍需提供附加的配|项目到web-server或servlet-container的结合体?
Apache上的实现
]]>
2. ?/span>web.xml中的<web-app></web-app>d如下代码Q?/span>
<security-role>
<description>Baron's role to log in administration application</description>
<role-name>admin</role-name>
</security-role>
<security-constraint>
<display-name>Baron security-constraint!</display-name>
<web-resource-collection>
<web-resource-name>Baron Protected Area</web-resource-name>
<url-pattern>*.jsp</url-pattern>
<url-pattern>*.htm</url-pattern>
</web-resource-collection>
<auth-constraint>
<role-name>admin</role-name>
</auth-constraint>
</security-constraint>
<login-config>
<auth-method>FORM</auth-method>
<realm-name>BaronRealm</realm-name>
<form-login-config>
<form-login-page>/usercheck.jsp</form-login-page>
<form-error-page>/error.jsp</form-error-page>
</form-login-config>
</login-config>
如果Ҏ(gu)有的web资源都进行保护,则作如下修改Q?/span>
<url-pattern>/*<url-pattern>
如果通过控制资源讉KҎ(gu)q行保护Q则?/span><web-resource-collection>
</web-resource-colleciont>作如下修改:
<http-method>DELETE</http-method>
<http-method>GET</http-method>
<http-method>POST</http-method>
<http-method>PUT</http-method>
以上为基于表单的验证Q如果改成基本验证(?span class="hilite2">安全Q,则作如下修改Q?/span>
<login-config>
<auth-method>BASIC</auth-method>
<realm-name>BaronRealm</realm-name>
</login-config>
如果Ҏ(gu)摘要验证Q则作如下修改:
<login-config>
<auth-method>DIGEST</auth-method>
<realm-name>BaronRealm</realm-name>
</login-config>
3. 1Q通过内存域验证,x?/span>tomcat-user.xml文g中的定义来验证登陆信?/span>
?/span>tomcat-users.xml中进行如下修改,d角色及用?/span>
<tomcat-users>
<role rolename="tomcat"/>
<role rolename="role1"/>
<role rolename="admin"/>
<user username="tomcat" password="tomcat" roles="tomcat"/>
<user username="role1" password="tomcat" roles="role1"/>
<user username="both" password="tomcat" roles="tomcat,role1"/>
<user username="baron" password="baron" roles="admin"/>
</tomcat-users>
?/span>server.xml中的<Context></Context>中添加:
<Realm className="org.apache.catalina.realm.MemoryRealm"/>
2Q通过DataSource域验?/span>
user_roles,字段user_name,role_name
<ResourceParams>元素:
<Resource auth="Container" name="jdbc/BaronDB" type="javax.sql.DataSource"/>
<ResourceParams name="jdbc/BaronDB">
<parameter>
<name>factory</name>
<value>org.apache.commons.dbcp.BasicDataSourceFactory</value>
</parameter>
<parameter>
<name>url</name>
<value>jdbc:microsoft:sqlserver://localhost:1433;DatabaseName=guard</value>
</parameter>
<parameter>
<name>password</name>
<value>229</value>
</parameter>
<parameter>
<name>maxWait</name>
<value>10000</value>
</parameter>
<parameter>
<name>maxActive</name>
<value>100</value>
</parameter>
<parameter>
<name>driverClassName</name>
<value>com.microsoft.jdbc.sqlserver.SQLServerDriver</value>
</parameter>
<parameter>
<name>username</name>
<value>sa</value>
</parameter>
<parameter>
<name>maxIdle</name>
<value>30</value>
</parameter>
</ResourceParams>
<Realm className="org.apache.catalina.realm.DataSourceRealm"
debug="99"
dataSourceName="jdbc/BaronDB"
userTable="b_users" userNameCol="user_name" userCredCol="user_password"
userRoleTable="b_user_roles" roleNameCol="role_name"/>
*.?/span>web.xml中无d?/span><resource-ref>声明?/span>DataSource的引?/span>
*.在页面中调用request.getRemoteUser()可得到当前访问的用户?/span>