精华内容
下载资源
问答
  • Tomcat服务器配置server....Tomcat 服务器的配置主要集中于** tomcat/conf **下的 catalina.policy、catalina.properties、context.xmlserver.xml、tomcat-users.xml、web.xml 文件 server.xml server.xml 是tomc

    Tomcat 服务器的配置主要集中于** tomcat/conf **下的 catalina.policy、catalina.properties、context.xml、server.xml、tomcat-users.xml、web.xml 文件

    server.xml

    server.xml 是tomcat 服务器的核心配置文件,包含了Tomcat的 Servlet 容器(Catalina)的所有配置。由于配置的属性特别多,我们在这里主要讲解其中的一部分重要配置。

    Server

    Server是server.xml的根元素,用于创建一个Server实例,默认使用的实现类是**org.apache.catalina.core.StandardServer**

    <Server port="8005" shutdown="SHUTDOWN">
    	...
    </Server>
    
    
    1. port : Tomcat 监听的关闭服务器的端口。

    2. shutdown: 关闭服务器的指令字符串。

    3. Server内嵌的子元素为 Listener、GlobalNamingResources、Service。

    默认配置的5个Listener 的含义:

    <!‐‐ 用于以日志形式输出服务器 、操作系统、JVM的版本信息 ‐‐>
    <Listener className="org.apache.catalina.startup.VersionLoggerListener"/>
    <!‐‐ 用于加载(服务器启动)和销毁(服务器停止)APR。如果找不到APR库,则会
    输出日志,并不影响Tomcat启动 ‐‐>
    <Listener className="org.apache.catalina.core.AprLifecycleListener"
     SSLEngine="on" />
    <!‐‐ 用于避免JRE内存泄漏问题 ‐‐>
    <Listener
     className="org.apache.catalina.core.JreMemoryLeakPreventionListener" />
    <!‐‐ 用户加载(服务器启动)和销毁(服务器停止)全局命名服务 ‐‐>
    <Listener
     className="org.apache.catalina.mbeans.GlobalResourcesLifecycleListener" />
    <!‐‐ 用于在Context停止时重建Executor 池中的线程, 以避免ThreadLocal 相关的内
    存泄漏 ‐‐>
    <Listener
     className="org.apache.catalina.core.ThreadLocalLeakPreventionListener" />
    
    

    GlobalNamingResources 中定义了全局命名服务:

    
    <!‐‐ Global JNDI resources
     Documentation at /docs/jndi‐resources‐howto.html ‐‐>
    <GlobalNamingResources>
    <!‐‐ Editable user database that can also be used by
     UserDatabaseRealm to authenticate users ‐‐>
    <Resource name="UserDatabase" auth="Container"
    	type="org.apache.catalina.UserDatabase"
    	description="User database that can be updated and saved"
    	factory="org.apache.catalina.users.MemoryUserDatabaseFactory"
    pathname="conf/tomcat‐users.xml" />
    </GlobalNamingResources>
    
    

    Service

    该元素用于创建 Service 实例,默认使用 org.apache.catalina.core.StandardService。默认情况下,Tomcat 仅指定了Service 的名称, 值为 “Catalina”。Service 可以内嵌的元素为 : Listener、Executor、Connector、Engine,其中 : Listener 用于为Service添加生命周期监听器, Executor 用于配置Service 共享线程池,Connector 用于配置Service 包含的链接器, Engine 用于配置Service中链接器对应的Servlet 容器引擎。

    <Service name="Catalina">
    ...
    </Service>
    
    

    一个Server服务器,可以包含多个Service服务

    Executor

    默认情况下,Service 并未添加共享线程池配置。 如果我们想添加一个线程池, 可以在下添加如下配置:

    <Executor name="tomcatThreadPool"
    	namePrefix="catalina‐exec‐"
    	maxThreads="200"
    	minSpareThreads="100"
    	maxIdleTime="60000"
    	maxQueueSize="Integer.MAX_VALUE"
    	prestartminSpareThreads="false"
    	threadPriority="5"
    	className="org.apache.catalina.core.StandardThreadExecutor" />
    
    

    属性说明:

    属性含义
    name线程池名称,用于 Connector中指定。
    namePrefix所创建的每个线程的名称前缀,一个单独的线程名称为namePrefix+threadNumber。
    maxThreads池中最大线程数。
    minSpareThreads活跃线程数,也就是核心池线程数,这些线程不会被销毁,会一直存在。
    maxIdleTime线程空闲时间,超过该时间后,空闲线程会被销毁,默认值为6000(1分钟),单位毫秒。
    maxQueueSize在被执行前最大线程排队数目,默认为Int的最大值,也就是广义的无限。除非特殊情况,这个值不需要更改,否则会有请求不会被处理的情况发生。
    prestartminSpareThreads启动线程池时是否启动 minSpareThreads部分线程。
    默认值为false,即不启动。
    threadPriority线程池中线程优先级,默认值为5,值从1到10。
                                                                                              |
    

    | className | 线程池实现类,未指定情况下,默认实现类为org.apache.catalina.core.StandardThreadExecutor。
    如果想使用自定义线程池首先需要实现org.apache.catalina.Executor接口。 |

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-em28JDDX-1622718638102)(https://tcs.teambition.net/storage/31267f5a478bca357393c76f5962f206544d?Signature=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJBcHBJRCI6IjU5Mzc3MGZmODM5NjMyMDAyZTAzNThmMSIsIl9hcHBJZCI6IjU5Mzc3MGZmODM5NjMyMDAyZTAzNThmMSIsIl9vcmdhbml6YXRpb25JZCI6IiIsImV4cCI6MTYyMzMyMzM1MCwiaWF0IjoxNjIyNzE4NTUwLCJyZXNvdXJjZSI6Ii9zdG9yYWdlLzMxMjY3ZjVhNDc4YmNhMzU3MzkzYzc2ZjU5NjJmMjA2NTQ0ZCJ9.-KX8md9-zQSQ96Q5h-OwXsDPLIjHJT5VjWF6xgg4ewo&download=image.png “”)]

    如果不配置共享线程池,那么Catalina 各组件在用到线程池时会独立创建。

    Connector

    Connector 用于创建链接器实例。默认情况下,server.xml 配置了两个链接器,一个支持HTTP协议,一个支持AJP协议。因此大多数情况下,我们并不需要新增链接器配置,只是根据需要对已有链接器进行优化。

    
    <Connector port="8080" protocol="HTTP/1.1" connectionTimeout="20000" redirectPort="8443" />
    <Connector port="8009" protocol="AJP/1.3" redirectPort="8443" />
    
    

    属性说明:

    • port: 端口号,Connector 用于创建服务端Socket 并进行监听, 以等待客户端请求链接。如果该属性设置为0,Tomcat将会随机选择一个可用的端口号给当前Connector使用。

    • **protocol **: 当前Connector 支持的访问协议。 默认为 HTTP/1.1 , 并采用自动切换机制选择一个基于 JAVA NIO 的链接器或者基于本地APR的链接器(根据本地是否含有Tomcat的本地库判定)。

    如果不希望采用上述自动切换的机制, 而是明确指定协议, 可以使用以下值:

    **Http协议: **

    org.apache.coyote.http11.Http11NioProtocol , 非阻塞式 Java NIO 链接器
    org.apache.coyote.http11.Http11Nio2Protocol , 非阻塞式 JAVA NIO2 链接器
    org.apache.coyote.http11.Http11AprProtocol , APR 链接器
    
    

    AJP协议:

    org.apache.coyote.ajp.AjpNioProtocol , 非阻塞式 Java NIO 链接器
    org.apache.coyote.ajp.AjpNio2Protocol ,非阻塞式 JAVA NIO2 链接器
    org.apache.coyote.ajp.AjpAprProtocol , APR 链接器
    
    
    • **connectionTimeOut **: Connector 接收链接后的等待超时时间, 单位为 毫秒。 -1 表示不超时。

    • redirectPort:当前Connector 不支持SSL请求, 接收到了一个请求, 并且也符合security-constraint 约束, 需要SSL传输,Catalina自动将请求重定向到指定的端口。

    • **executor **: 指定共享线程池的名称, 也可以通过maxThreads、minSpareThreads等属性配置内部线程池。

    • **URIEncoding **: 用于指定编码URI的字符编码, Tomcat8.x版本默认的编码为 UTF-8 ,Tomcat7.x版本默认为ISO-8859-1。

    完整配置如下:

    < Connector port="8080"
        protocol="HTTP/1.1"
        executor="tomcatThreadPool"
        maxThreads="1000"
        minSpareThreads="100"
        acceptCount="1000"
        maxConnections="1000"
        connectionTimeout="20000"
        compression="on"
        compressionMinSize="2048"
        disableUploadTimeout="true"
        redirectPort="8443"
        URIEncoding="UTF‐8" />
    
    

    Engine

    Engine 作为Servlet 引擎的顶级元素,内部可以嵌入: Cluster、Listener、Realm、Valve和Host。

    <Engine name="Catalina" defaultHost="localhost">
    ...
    </Engine>
    
    

    属性说明:

    1. name: 用于指定Engine 的名称, 默认为Catalina 。该名称会影响一部分Tomcat的存储路径(如临时文件)。

    2. **defaultHost **: 默认使用的虚拟主机名称, 当客户端请求指向的主机无效时, 将交由默认的虚拟主机处理, 默认为localhost,指定那个Host是默认的(可以是不存在的host)

    Host

    Host 元素用于配置一个虚拟主机, 它支持以下嵌入元素:Alias、Cluster、Listener、Valve、Realm、Context。如果在Engine下配置Realm, 那么此配置将在当前Engine下的所有Host中共享。 同样,如果在Host中配置Realm , 则在当前Host下的所有Context中共享。Context中的Realm优先级 > Host 的Realm优先级 > Engine中的Realm优先级

    <Host name="localhost" appBase="webapps" unpackWARs="true" autoDeploy="true">
    ...
    </Host>
    
    

    属性说明:

    • **name:**当前Host通用的网络名称, 必须与DNS服务器上的注册信息一致(hosts文件)。 Engine中包含的Host必须存在一个名称与Engine的defaultHost设置一致。

    • appBase:当前Host的应用基础目录, 当前Host上部署的Web应用均在该目录下(可以是绝对目录,相对路径)。默认为webapps。

    • unpackWARs:设置为true, Host在启动时会将appBase目录下war包解压为目录。设置为false, Host将直接从war文件启动。

    • autoDeploy:控制tomcat是否在运行时定期检测并自动部署新增或变更的web应用

    通过给Host添加别名,我们可以实现同一个Host拥有多个网络名称,配置如下:

    
    <Host name="www.web1.com" appBase="webapps" unpackWARs="true" autoDeploy="true">
        <Alias>www.web2.com</Alias>
    </Host>
    
    

    这个时候,我们就可以通过两个域名访问当前Host下的应用(需要确保DNS或hosts中添加了域名的映射配置)。

    Context

    Context 用于配置一个Web应用,默认的配置如下:

    
    <Context docBase="myApp" path="/myApp">
    ....
    </Context>
    
    

    属性描述:

    1. docBase:Web应用目录或者War包的部署路径。可以是绝对路径,也可以是相对于Host appBase的相对路径。

    2. path:Web应用的Context 路径。如果我们Host名为**localhost**, 则该web应用访问的根路径为: http://localhost:8080/myApp。它支持的内嵌元素为:CookieProcessor, Loader, Manager,Realm,Resources,WatchedResource,JarScanner,Valve。

    
    <Host name="www.tomcat.com" appBase="webapps" unpackWARs="true" autoDeploy="true">
        <Context docBase="D:\servlet_project03" path="/myApp"></Context>
        <Valve className="org.apache.catalina.valves.AccessLogValve" directory="logs"
        prefix="localhost_access_log" suffix=".txt"
        pattern="%h %l %u %t &quot;%r&quot; %s %b" />
    </Host>
    
    

    tomcat-user.xml

    该配置文件中,主要配置的是Tomcat的用户,角色等信息,用来控制Tomcat中manager, host-manager的访问权限。

    展开全文
  • server.xml从Web应用程序引用数据库属性META-INF/context.xml方法3的好处尽管出于安全原因第一点很有用,但第二点对于从Web应用程序引用服务器属性值也是有用的,即使服务器属性值会发生变化。此外,将服务器上的...

    小编典典

    我更喜欢第三种方法,该方法从 user1016403描述的方法1和方法2 中获得最大的收益。

    方法3

    1. 将数据库属性保存在 server.xml

    2. server.xml从Web应用程序引用数据库属性META-INF/context.xml

    方法3的好处

    尽管出于安全原因第一点很有用,但第二点对于从Web应用程序引用服务器属性值也是有用的,即使服务器属性值会发生变化。

    此外,将服务器上的资源定义与Web应用程序的使用脱钩可以使这种配置在具有各种复杂性的组织之间可扩展,其中不同的团队在不同的层/层上工作:如果管理员共享相同的资源,则服务器管理员团队可以在不与开发人员团队冲突的情况下工作每个资源的开发人员的JNDI名称。

    方法3的实施

    定义JNDI名称jdbc/ApplicationContext_DatabaseName。

    使用类似这样的声明jdbc/ApplicationContext_DatabaseName在Tomcat的各种属性和值server.xml:

    username="dbUsername" password="dbPasswd"

    url="jdbc:postgresql://localhost/dbname"

    driverClassName="org.postgresql.Driver"

    initialSize="5" maxWait="5000"

    maxActive="120" maxIdle="5"

    validationQuery="select 1"

    poolPreparedStatements="true"/>

    jdbc/ApplicationContext_DatabaseName通过属性META-INF/context.xml中java:comp/env/指定的应用程序专用JNDI上下文从网络应用程序链接的name属性:

    最后,为了使用JNDI资源,请jdbc/DatabaseName在Web应用程序的部署描述符中指定JNDI名称:

    DatabaseName's Datasource

    jdbc/DatabaseName

    javax.sql.DataSource

    Container

    在Spring上下文中:

    jndi-name="jdbc/DatabaseName"

    expected-type="javax.sql.DataSource" />

    方法3的缺点

    如果JNDI名称被更改,则必须同时编辑和server.xml和,META-INF/context.xml并且必须进行部署。但是,这种情况很少见。

    方法3的变化

    一个Web应用程序使用的许多数据源

    只需将配置添加到Tomcat的server.xml:

    ...

    META-INF/context.xml通过属性中java:comp/env/指定的应用程序专用JNDI上下文添加链接Web应用程序name:

    ...

    最后,在Web应用程序的部署描述符中添加JNDI资源使用情况:

    DatabaseName1's Datasource

    jdbc/DatabaseName1 ...

    DatabaseName2's Datasource

    jdbc/DatabaseName2 ...

    ...

    在Spring上下文中:

    jndi-name="jdbc/DatabaseName1" ... />

    jndi-name="jdbc/DatabaseName2" ... />

    ...

    同一台服务器上的许多Web应用程序使用的许多数据源

    只需将配置添加到Tomcat的server.xml:

    ...

    其他配置应该可以从以前的变化情况中得出。

    同一服务器上许多Web应用程序使用的同一数据库的许多数据源

    在这种情况下,Tomcat的server.xml配置如下:

    最终出现在两个不同的Web应用程序中,META-INF/context.xml 例如:

    像:

    所以有人可能会担心的是,同样name="jdbc/DatabaseName"是抬起头,然后使用由部署在同一服务器上的两个不同的应用程序:这不是一个问题,因为jdbc/DatabaseName是一个应用程序私有JNDI上下文java:comp/env/,因此ApplicationContextX 使用java:comp/env/不能(根据设计)查找链接到的资源global="jdbc/ApplicationContextY_DatabaseName"。

    当然,如果你放心而又不用担心,可以使用其他命名策略,例如:

    像:

    2020-04-17

    展开全文
  • 详细介绍了Tomcat服务器的server.xml配置文件结构,包括BIO与NIO模式,以及请求处理流程。

    详细介绍了Tomcat的核心组件以及server.xml配置全解,以及请求处理流程。

    前面我们简单介绍了Tomcat服务器的基本概念,现在我们来简单看看它的核心配置文件server.xml。

    本文将会介绍Tomcat中比较重要的一些配置和概念,而又不会太深入底层,本文并不是专业的Tomcat学习文章。如果你是Java学习者或者开发者,并且没有专门的时间和计划去详细学习Tomcat服务器,那么本文值得一看!

    1 server.xml文件概述

    tomcat是组件式架构,它的server.xml配置文件中可以通过标签配置tomcat容器中的不同类型的组件,是tomcat的核心配置文件。

    server.xml中的主要组件(标签)的关系如下(并没有展示全部组件的关系):

    在这里插入图片描述

    Server标签在最顶层,代表整个Tomcat容器;一个Server元素中可以有一个或多个Service元素。

    Service在Connector和Engine外面包了一层,把它们组装在一起,对外提供服务。一个Service可以包含多个Connector,但是只能包含一个Engine;Connector接收请求,Engine处理请求。

    Engine、Host和Context都是容器,且 Engine包含Host,Host包含Context。每个Host组件代表Engine中的一个虚拟主机;每个Context组件代表在特定Host上运行的一个Web应用。

    tomcat 8.5.61的默认server.xml的配置如下:

    <?xml version="1.0" encoding="UTF-8"?>
    <!--
    Server是server.xml的最外层标签,代表整个tomcat容器
    它的内部不能直接定义<Value/>组件
    -->
    <Server port="8005" shutdown="SHUTDOWN">
        <!--监听器组件-->
        <Listener className="org.apache.catalina.startup.VersionLoggerListener"/>
        <Listener className="org.apache.catalina.core.AprLifecycleListener" SSLEngine="on"/>
        <Listener className="org.apache.catalina.core.JreMemoryLeakPreventionListener"/>
        <Listener className="org.apache.catalina.mbeans.GlobalResourcesLifecycleListener"/>
        <Listener className="org.apache.catalina.core.ThreadLocalLeakPreventionListener"/>
    
        <!--配置全局JNDI资源-->
        <GlobalNamingResources>
            <!-- 用户数据库Realm,也可以用于对用户进行身份验证的可编辑用户数据库 -->
            <Resource name="UserDatabase" auth="Container"
                      type="org.apache.catalina.UserDatabase"
                      description="User database that can be updated and saved"
                      factory="org.apache.catalina.users.MemoryUserDatabaseFactory"
                      pathname="conf/tomcat-users.xml"/>
        </GlobalNamingResources>
    
        <!--
        将<Engine/>标签和<Connector/>标签组合在一起,对外提供服务,一个Server元素中可以有一个或多个Service元素
        包含一个<Engine/>标签,以及一个或多个<Connector/>标签,<Connector/>标签共享用同一个<Engine/>标签
        它的内部不能直接定义<Value/>组件
        -->
        <Service name="Catalina">
            <!-- 供Service内各个Connector组件共享使用的线程池执行器,我们可以定义的多个命名线程池 -->
            <!--
            <Executor name="tomcatThreadPool" namePrefix="catalina-exec-"
                maxThreads="150" minSpareThreads="4"/>
            -->
    
    
            <!-- 连接器组件,主要用于接收连接请求,创建Request和Response对象用于和请求端交换数据
                 然后分配线程让Engine来处理这个请求,并把产生的Request和Response对象传给Engine。
    
                 在端口8080上定义使用HTTP/1.1协议的连接器,这就是默认连接器,基于BIO运行模式
            -->
            <Connector port="8080" protocol="HTTP/1.1"
                       connectionTimeout="20000"
                       redirectPort="8443"/>
    
            <!-- 使用指定命名共享线程池的连接器 -->
            <!--
            <Connector executor="tomcatThreadPool"
                       port="8080" protocol="HTTP/1.1"
                       connectionTimeout="20000"
                       redirectPort="8443" />
            -->
    
            <!--在端口8443上定义使用Http11NioProtocol协议的连接器,是一个基于Non-blocking 的 NIO运行模式的Connector,即非阻塞IO,性能更好-->
            <!--
            <Connector port="8443" protocol="org.apache.coyote.http11.Http11NioProtocol"
                       maxThreads="150" SSLEnabled="true">
                <SSLHostConfig>
                    <Certificate certificateKeystoreFile="conf/localhost-rsa.jks"
                                 type="RSA" />
                </SSLHostConfig>
            </Connector>
            -->
    
            <!--在端口8443上定义使用Apr运行模式的连接器,在高并发下性能相比于NIO的连接器更加优越-->
            <!--
            <Connector port="8443" protocol="org.apache.coyote.http11.Http11AprProtocol"
                       maxThreads="150" SSLEnabled="true" >
                <UpgradeProtocol className="org.apache.coyote.http2.Http2Protocol" />
                <SSLHostConfig>
                    <Certificate certificateKeyFile="conf/localhost-rsa-key.pem"
                                 certificateFile="conf/localhost-rsa-cert.pem"
                                 certificateChainFile="conf/localhost-rsa-chain.pem"
                                 type="RSA" />
                </SSLHostConfig>
            </Connector>
            -->
    
            <!--在端口8009上定义使用AJP/1.3协议访问的连接器-->
            <!--
            <Connector protocol="AJP/1.3"
                       address="::1"
                       port="8009"
                       redirectPort="8443" />
            -->
    
            <!--
            请求处理组件,一个Service标签只能有一个Engine标签
            Engine组件从一个或多个Connector中接收请求并处理,并将完成的响应返回给Connector,最终响应给客户端。
            -->
            <Engine name="Catalina" defaultHost="localhost">
    
                <!--For clustering, please take a look at documentation at:
                    /docs/cluster-howto.html  (simple how to)
                    /docs/config/cluster.html (reference documentation) -->
                <!--
                Tomcat集群配置组件,详情参考:
                /docs/cluster-howto.html(简单配置)
                /docs/config/cluster.html(reference documentation)
                -->
                <!--
                <Cluster className="org.apache.catalina.ha.tcp.SimpleTcpCluster"/>
                -->
    
                <!-- Use the LockOutRealm to prevent attempts to guess user passwords via a brute-force attack -->
                <!--
                Realm可以理解为包含用户名、密码、角色的"数据库",或者"域"
                Realm提供了一种用户密码与web应用的映射关系,从而达到角色安全管理的作用
                这里使用 LockOutRealm 防止试图通过暴力攻击猜测用户密码
                -->
                <Realm className="org.apache.catalina.realm.LockOutRealm">
                    <!-- This Realm uses the UserDatabase configured in the global JNDI
                         resources under the key "UserDatabase".  Any edits
                         that are performed against this UserDatabase are immediately
                         available for use by the Realm.  -->
                    <Realm className="org.apache.catalina.realm.UserDatabaseRealm"
                           resourceName="UserDatabase"/>
                </Realm>
                <!--
                一个虚拟主机,可以指定应用程序的基本目录,包含了一个或多个Web应用
                默认的虚拟主机名为"localhost",
                -->
                <Host name="localhost" appBase="webapps"
                      unpackWARs="true" autoDeploy="true">
                    <!--通过日志记录其该Host中处理的所有请求-->
                    <Valve className="org.apache.catalina.valves.AccessLogValve" directory="logs"
                           prefix="localhost_access_log" suffix=".txt"
                           pattern="%h %l %u %t &quot;%r&quot; %s %b"/>
    
                </Host>
            </Engine>
        </Service>
    </Server>
    

    下面来简单的认识一下核心组件(标签)的作用以及配置。本文以tomcat 8.5.61版本为主。

    2 Server

    Server标签是server.xml文件的根标签,代表整个tomcat的Servlet容器,时tomcat的核心组件,是Tomcat实例的顶层的org.apache.catalina.Server接口的抽象。

    Server标签的属性表示 servlet 容器的一个整体的特征。常见属性如下:

    属性名描述
    className要使用的Java 实现类全路径名,指定的类必须实现org.apache.catalina.Server.Server 接口。如果未指定类名,则将使用标准实现,即org.apache.catalina.core.StandardServer
    addresstomcat监听shutdown命令的TCP/IP地址,如未指定,则默认为localhost
    porttomcat监听shutdown命令的TCP/IP端口号,默认为8005。设置为-1,表示禁止通过端口关闭Tomcat,此时shutdown.bat命令不能使用。如果一台及其启动多个tomcat实例,该端口应该不一致。
    shutdown通过指定的地址(address)和端口(port)关闭tomcat时所需发送的终止字符串,默认为“SHUTDOWN”,修改shutdown的值,对shutdown.bat的使用无影响。

    Server标签内部可以配置一个或者多个Listener标签,一个或者多个Service标签以及一个GlobalNamingResources标签。

    2 Listener

    一个Listener标签表示配置的一个tomcat的监听器组件。一个监听器负责监听特定的事件,当特定事件触发时,Listener会捕捉到该事件并做出相应处理。

    Listener可嵌在Server、Engine、Host、Context标签内,不得将任何其他标签元素嵌套在监听器标签中。某些特殊类型的监听器仅用于嵌套在特定标签中,默认配置的监听器都是在Server标签内。Listener通常用于监听Tomcat的启动和关闭事件。

    所有监听器都有的属性如下:

    属性名描述
    className要使用的Java 监听器实现类全路径名,指定的类必须实现org.apache.catalina.LifecycleListener 接口。

    本文使用的tomcat版本中,默认开启的五个监听器配置如下:

    在这里插入图片描述

    常见的监听器介绍如下:

    1. VersionLoggerListener :版本日志记录生命周期监听器。当Tomcat启动时,该监听器记录Tomcat、Java和操作系统的信息。该类型的监听器必须只能嵌套在Server标签中,并且必须是配置的第一个监听器。
    2. AprLifecycleListener :APR 生命周期监听器。Tomcat启动时检查APR库,如果存在则加载。APR,即Apache Portable Runtime,是Apache可移植运行库,可以实现高可扩展性、高性能,以及与本地服务器技术更好的集成。该类型的监听器必须只能嵌套在Server标签中。Tomcat将以JNI的形式调用Apache HTTP服务器的核心动态链接库来处理文件读取或网络传输操作,从而大大地提高Tomcat对静态文件的处理性能。
    3. JreMemoryLeakPreventionListener:JRE 内存泄漏防护监听器。这个监听器会导致每小时就执行一次full GC操作,因此可以直接关闭这个监听器,或者添加gcDaemonProtection="false"属性来进制监听。该类型的监听器必须只能嵌套在Server标签中。
    4. GlobalResourcesLifecycleListener:全局资源生命周期监听器。通过该监听器,可以初始化< GlobalNamingResources/>标签中定义的全局JNDI资源;如果没有该监听器,任何全局资源都不能使用。该类型的监听器必须只能嵌套在Server标签中。
    5. ThreadLocalLeakPreventionListener:ThreadLocal泄漏防护监听器。当一个Web应用(context标签)停止时,该监听器器将触发执行器池中的线程更新,以避免线程本地相关内存泄漏。当线程执行完任务被收回线程池时,活跃线程会一个一个的更新。只有当Web应用(context标签)的renewThreadsWhenStoppingContext属性设置为true时,该监听器才有效。
    6. SecurityListener:安全生命周期监听器。当 Tomcat 启动时,该监听器将执行许多安全检查,并防止 Tomcat 在检查失败时启动。默认情况下未启用该侦听器。
    7. JasperListener:在Web应用启动之前初始化Jasper,Jasper是JSP引擎,把JVM不认识的JSP文件解析成java文件,然后编译成class文件供JVM使用。

    3 GlobalNamingResources

    全局命名资源组件,定义服务器的全局JNDI资源,所有的应用程序都可以引用。通常可以包含三个子标签:Environment、Resource、ResourceEnvRef。

    JNDI(Java Naming and Directory Interface)多用于java的数据库连接中,我们常见的就是JDBC,在JDBC中,连接数据库需要用户名、用户名密码和数据库名称等参数,将来如果这三个参数中的任何一个修改,则整个程序中相关的地方都需要修改,简直是牵一发而动全身,因此出现JNDI技术。

    在JNDI中,将连接数据库需要的用户、用户密码和数据库名称等JDBC引用的参数定义为一个整体(即这个整体中包含JDBC要用到类库、数据库驱动程序、用户、用户密码等),然后为这个整体设置一个名称,这个整体保存在应用程序之外的文件中,这样以后连接数据库的时候直接在程序中引用这个整体的名称即可,无论用户、用户密码怎么变换,只要这个整体的名称不变,我们仅要修改这个外部的整体的用户和用户密码,而无需修改整个程序。这里的这个整体就是JNDI数据源(JNDI资源)。对于数据库来说,JNDI数据源避免了程序与数据库之间的紧耦合,使应用更加易于配置、易于部署。

    3.1 Environment

    Environment标签可以用于配置全部项目的环境变量。比如:

    <GlobalNamingResources ...>
    ...
    <Environment name="maxExemptions" value="10"
           type="java.lang.Integer" override="false"/>
    ...
    </GlobalNamingResources>
    

    它表示配置一个名为maxExemptions的Integer类型的环境变量,值为10。如果想要在具体的Web应用中引用该常量,那么在具体应用的Context标签下,使用ResourceLink标签引用该Environment资源,global属性就是该Environment的name属性名字。

    这等同于在web应用的/WEB-INF/web.xml文件中的如下配置:

    <env-entry>
      <env-entry-name>maxExemptions</env-entry-name>
      <env-entry-value>10</env-entry-value>
      <env-entry-type>java.lang.Integer</env-entry-type>
    </env-entry>
    

    在Java代码中使用如下方式读取:

    Context initCtx = null;
    initCtx = new InitialContext();
    Context envCtx = (Context)initCtx.lookup("java:comp/env");
    Integer n = (Integer)envCtx.lookup("maxExemptions");
    

    3.2 Resource

    Resource标签可以用于配置各种全局数据源,最常见的就是用户数据库连接JNDI源。下面表示通过JNDI配置一个数据库数据源。

    <GlobalNamingResources>       
        <Resource 
          name="DbSource" 
          username="admin"
          password="123456" 
          maxIdle="30" 
          maxActive="50"
          maxWait="5000"
          type="javax.sql.DataSource"
          driverClassName="com.mysql.jdbc.Driver" 
          url="jdbc:xxx" />
    </GlobalNamingResources>
    

    然后在Web应用(context标签)下通过ResourceLink标签引用数据源:

    <ResourceLink global="DbSource" name="DbSource" type="javax.sql.DataSource"/>
    

    随后在Spring配置文件中可以配置引用JNDI数据源:

    <beans>
      <bean id="dataSource" class="org.springframework.jndi.JndiObjectFactoryBean">
        <property name="jndiName">
            <value>java:/comp/env/ DbSource</value>
        </property> 
      </bean>
    </beans>
    

    也可以使用Java代码获取:

    //获得对数据源的引用:
    Context ctx = new InitalContext();
    DataSource ds = (DataSource)ctx.lookup("java:comp/env/DbSource");
    //获得数据库连接对象:
    Connection con = ds.getConnection();
    //返回数据库连接到连接池:
    con.close();
    

    3.2.1 manager

    Tomcat manager是Tomcat自带的、使用HTML界面的、管理Tomcat自身以及部署在Tomcat上的应用的web应用。

    在这里插入图片描述

    manager需要使用用户登陆并根据角色分配权限,角色和用户在tomcat-users.xml中配置。tomcat的tomcat-users.xml文件中默认没有配置任何用户信息:

    在这里插入图片描述

    tomcat-users.xml文件中的配置信息是tomcat8在server.xml中默认配置了的一个用户数据库数据源来加载的:

    <!--配置全局JNDI资源-->
    <GlobalNamingResources>
        <!-- 用户数据库Realm,也可以用于对用户进行身份验证的可编辑用户数据库 -->
        <Resource name="UserDatabase" auth="Container"
                  type="org.apache.catalina.UserDatabase"
                  description="User database that can be updated and saved"
                  factory="org.apache.catalina.users.MemoryUserDatabaseFactory"
                  pathname="conf/tomcat-users.xml"/>
    </GlobalNamingResources>
    

    该示例表示定义了一个名为UserDataBase的全局JNDI数据源,使用容器管理该Resource,该数据源为加载tomcat-users.xml文件至内存中而定义的用于用户授权的数据库。然后在认证文件tomcat-users.xml中就可以配置可以访问Manager App和Host Manager页面的用户以及权限。在Engine标签下可以通过Realm标签来引用配置的数据源,resourceName属性的值就是Resource标签的name属性值。

    上面的配置中role标签用来配置角色,user标签用来配置用户。如果我们在tomcat-users.xml中添加如下配置:

    在这里插入图片描述

    表示登陆用户名为admin,用户密码为123456,用户权限为admin-gui和admin-script,admin-gui表示允许访问 Host Manager的html接口(即URL路径为/host-manager/html/*),admin-script表示允许访问 Host Manager的纯文本接口(即URL路径为/host-manager/text/*)。此时我们就可以访问Host Manager页面。

    在这里插入图片描述

    对于Manager App页面,我们则需要配置如下几个权限:

    1. manager-gui:允许访问html接口(即URL路径为/manager/html/*)。
    2. manager-script:允许访问纯文本接口(即URL路径为/manager/text/*)。
    3. manager-jmx:允许访问JMX代理接口(即URL路径为/manager/jmxproxy/*)。
    4. manager-status:允许访问Tomcat只读状态页面(即URL路径为/manager/status/*)。

    manager-gui、manager-script、manager-jmx均具备manager-status的权限,也就是说,manager-gui、manager-script、manager-jmx三种角色权限无需再额外添加manager-status权限,即可直接访问路径/manager/status/*。

    4 Service

    包含一个Engine和多个Connector的服务组件,表示org.apache.catalina.Service接口,用于对外提供Web服务。不同的Connector接收不同的客户端请求,多个Connector共用一个Engine来处理所有Connector接收到的请求。

    Server中可以包括多个Service标签,Service标签内部不能直接定义< Value/>组件。tomcat8的默认配置中包含一个名为Catalina的Service组件。

    在这里插入图片描述

    Service的所有实现都支持以下属性:

    属性名描述
    className要使用的Java实现类全路径名,指定的类必须实现org.apache.catalina.Service接口。如果未指定类名,则将使用标准实现,即org.apache.catalina.core.StandardService
    nameService组件的名字,必须唯一

    5 Executor

    Executor即线程池执行器,一个Service中可以配置多个命名线程池,可以由其他组件共享使用,一般来说,使用线程池的是Connector组件,用于处理Http请求,要使用指定的线程池执行器,组件需要通过executor属性指定对应线程池的name属性。

    为了使Connector能正常使用线程池,Executor元素应该放在Connector前面。

    执行器的所有实现都支持以下属性:

    属性名描述
    className要使用的Java 实现类全路径名,指定的类必须实现org.apache.catalina.Executor 接口。如果未指定类名,则将使用标准实现,即org.apache.catalina.core.StandardThreadExecutor
    name执行器的名字,其他组件通过名字引用该执行器,因此该属性是必需的,并且必须是唯一的

    默认执行器实现支持以下属性:

    属性名描述
    threadPriorityExecutor内的线程的优先级,默认值为5(Thread.NORM_PRIORITY)
    daemonExecutor内的线程是否是后台线程,默认值true
    namePrefixExecutor创建的每个线程的名称前缀,线程池中线程名字为:namePrefix+ threadNumber
    maxThreadsExecutor中最大活跃线程数,默认值200(Tomcat7和8都是) ,即处理请求的最大线程数。
    minSpareThreadsExecutor中保持的最小线程数(无论是否是空闲状态),默认值是25
    maxIdleTimeExecutor中空闲线程超时关闭的毫秒数(除非线程数小于或等于 minSpareThread)。默认值为 60000(1 分钟)
    maxQueueSize在Executor执行拒绝策略之前,可以排队等待执行的最大可运行任务数,即任务队列的最大长度。默认值为Integer.MAX_VALUE((2147483647)
    prestartminSpareThreads启动Executor时是否应立即预初始化minSpareThread线程,默认值为false
    threadRenewalDelay如果配置了ThreadLocalLeakPreventionListener(默认会配置),监听器,它将通知此Executor有关的以停止的Web应用(context),停止Web应用后,池中的线程将重建。threadRenewalDelay表示重建线程的时间间隔,重建线程池内的线程时,为了避免线程同时重建,每隔threadRenewalDelay(毫秒)重建一个线程,默认值为1000,设置为负数则不重建

    6 Connector

    一个Connector标签代表一个与客户端实际交互的组件,负责接收客户端请求和返回响应结果。Connector标签位于Service标签下,一个Service标签可以包含多个Connector标签。

    在tomcat程序中,Connector将会为每个请求创建Request和Response对象,然后分配线程让Engine(Servlet实例)来处理这个请求,并把产生的Request和Response对象传给Engine,当Engine处理完请求后,也会通过Connector将响应返回给客户端。可以说,Servlet容器处理请求,是需要Connector进行调度和控制的,Connector是Tomcat处理请求的主干之一。

    我们着重要掌握连接器的属性,面试的时候经常问的tomcat的并发数量之类的都可以通过连接器设置。

    连接器的所有实现都支持以下常用属性:

    1. port:连接器监听的请求端口,必须唯一。如果使用特殊值 0,则 Tomcat 将随机选择一个自由端口用于此连接器。
    2. protocol:连接器监听的请求协议类型,以及使用何种模式来接受和处理请求,默认为 HTTP/1.1类型,并且兼容HTTP1.0。tomcat6开始支持NIO,在tomcat8中增加了对NIO2的支持,tomcat8.5去除了BIO(org.apache.coyote.http11.Http11Protocol)的支持。对于HTTP协议,tomcat8中可以设置如下值:
      1. HTTP/1.1:默认值,使用的协议与Tomcat版本有关,并且会自动选取。在Tomcat7中,自动选取使用BIO或APR(如果找到APR需要的本地库,则使用APR,否则使用BIO);在Tomcat8中,自动选取使用NIO或APR(如果找到APR需要的本地库,则使用APR,否则使用NIO)。
      2. org.apache.coyote.http11.Http11NioProtocol:NIO,non blocking Java NIO connector
      3. org.apache.coyote.http11.Http11Nio2Protocol:NIO2,non blocking Java NIO2 connector
      4. org.apache.coyote.http11.Http11AprProtocol:APR,the APR/native connector.
      5. org.apache.coyote.http11.Http11Protocol:BIO,tomcat8.5已取消支持。
    3. 另外还可以设置使用AJP协议,即protocol=“AJP/1.3”。AJP协议是应用在Apache在反向代理tomcat的场景,Apache和tomcat之间就是使用AJP协议通信,它是一种二进制协议。
    4. redirectPort:如果当前连接器不支持SSL(HTTPS)请求,但是收到SSL(HTTPS)请求时,Catalina将重定向至指定端口的Connector。
    5. URIEncoding:用于解码URL的字符编码,如果未指定,则默认使用 UTF-8,除非org.apache.catalina.STRICT_SERVLET_COMPLIANCE系统属性设置为 true,在这种情况下,将使用 ISO-8859-1。因此,tomcat8的get请求中的中文参数不需要再另行处理乱码问题了(此前的低版本默认是ISO8859-1)。
    6. maxPostSize:POST方法能够提交的数据的最大大小(byte)。通过将此属性设置为小于0的值,则表示不限制。如果未指定该属性,则此属性设置为 2097152(2 MB)。请注意,失败请求筛选器FailedRequestFilter可用于拒绝超过此限制的请求。
    7. enableLookups:如果要需要在调用request.getRemoteHost()时执行 DNS 查找以返回远程客户端的实际主机名,那么需要设置为 true。设置为 false 表示会跳过 DNS 查找,并且以String 形式返回 IP 地址(从而提高性能)。默认情况下为false,将禁用 DNS 查找。
    8. allowTrace:用于配置服务器能够处理用户的HAED/TRACE请求。如果未指定,则此属性设置为 false,表示不能。

    除了上面的属性之外,标准 HTTP 连接器(NIO, NIO2 and APR/native)还支持下面的常见属性:

    1. connectionTimeout:此连接器在建立连接之后等待请求URI的超时时间(毫秒),使用值 -1 表示无超时时间,默认值为60000(即 60秒)。当client与tomcat建立连接之后,在"connectionTimeout"时间之内,仍然没有得到client的请求数据,此时连接将会被断开。
    2. keepAliveTimeout:此连接器在关闭连接之前将等待另一个 HTTP 请求的超时时间(毫秒)。默认值是使用已为connectionTimeout属性设置的值,使用值 -1 表示无超时时间。
    3. maxConnections:tomcat在任何给定时间能同时接收和处理的最大连接数(不一定会被立即处理)。当Tomcat接收的连接数达到maxConnections时,Acceptor线程不会读取Accept队列中的连接;则Acceptor线程会一直阻塞着,直到Tomcat接收的连接数小于maxConnections。如果设置为-1,则连接数不受限制。
      1. 默认值因连接器类型而异。对于 NIO 和 NIO2,默认值为 10000,而BIO的默认值为maxThreads(如果配置了Executor,则默认值是Executor的maxThreads)。对于 APR/native,默认值为 8192,并且如果配置的值不是1024的倍数,maxConnections 的实际值将减少到1024的最大倍数。
    4. acceptCount:当同时连接数超过maxConnections时,系统会继续接收连接,但是传入的连接请求将在Accept等待队列等待而不会被Accepter拉取。该属性表示Accept等待队列的长度,如果等待队列也满了,那么收到的任何请求都将被直接被拒绝(返回connection refused)。默认值为100。
      1. 所以说,tomcat的可同时接收的最大连接数为maxConnections+acceptCount,对于BIO来说就是300
    5. maxThreads:每一次HTTP请求到达Web服务并建立连接之后,tomcat都会尝试创建一个线程来处理该请求。该属性表示此连接器可以创建的最大请求处理线程数,因此它决定连接器真正的可同时处理的用户请求的最大数量。如果未指定,则此属性默认设置为200。如果该Connector绑定了Executor,这个值会被忽略,因为该Connector将使用绑定的Executor,而不是内置的线程池来执行任务。
    6. executor:对 Executor 标签中name的引用。如果设置了此属性,并且存在指定的命名执行器,则该连接器将使用指定的执行器线程池,并且将忽略所有其他默认线程池属性,如果设置了默认执行器的属性,那么将报告一个-1来表示不会使用设置的属性。如果没有为连接器指定共享执行器,则连接器将使用专用的内部执行器提供线程池。
      1. 默认执行器线程命名通常是http-nio-,或者http-bio-。
    7. threadPriority:连接器的内部执行器中的请求处理线程的优先级。默认值为 5(java.lang.Thread.NORM_PRIORITY常量)。
    8. minSpareThreads:连接器的内部执行器保持的最小线程数(无论是否是空闲状态),默认值是10。
    9. SSLEnabled:设置此连接器是否开启SSL(HTTPS)的支持,如果需要开启,请将此值设置为 true。默认值为 false。将此值设置为 true 时,还需要设置scheme和secure这两个属性,即scheme=“https” secure=“true”。
    10. maxHttpHeaderSize:HTTP请求、响应头信息的最大大小,以字节为单位指定。如果未指定,此属性将设置为 8192 bytes(即8 KB)。

    在tomcat8的默认配置中,只开放了一个Connector,其他的Connector则被注释了:

    在这里插入图片描述

    根据上面的属性,这个开放出来的Connector表示:客户端可以通过8080端口号使用HTTP/1.1协议(兼容HTTP1.0)访问tomcat,建立连接之后等待请求URI的超时时间为20000ms(即 20秒),并且当出现HTTPS请求时,该HTTPS请求将被转发至端口号为8443的Connector(从注释中可以看到端口号为8443的Connector设置了SSLEnabled=“true”,即支持处理HTTPS请求)。

    http协议默认端口号为80,也就是说在URL中不给出端口号时就表示使用80端口。当然你也可以修改为其它端口号。当把端口号修改为80后,在浏览器中只需要输入:http://localhost就可以访问tomcat主页了。

    7 Engine

    Engine(引擎)表示一个与某个Service关联的请求处理组件,它接收并处理来自该Service中全部Connectors连接器接收到并封装的来自客户端的请求,并返回给连接器的已完成响应,以最终在通过连接器将响应传输回客户端。

    Engine可以看作Servlet容器,即container。 由org.apahce.catalina.Engine接口定义。一个Service中有且只能有一个Engine组件。

    Engine的所有实现都支持以下常见属性:

    属性名描述
    nameEngine的名称,用于日志和错误信息。在同一服务器中使用多个 Service 元素时,必须为每个Engine分配一个唯一的名称。
    defaultHost默认host主机名,当发往本机的请求指定的host名称不存在或者未指定时,一律使用defaultHost指定的host进行处理,因此此名称必须与内部的一个Host标签元素的name属性匹配。
    jvmRoute必须在负载平衡方案中使用的标识符,以启用session相关性。 主要是应用于tomcat集群中的session共享,会在一次会话中添加该值,获得session sticky
    className指定org.apache.catalina.Engine接口的实现类全路径名,默认值为org.apache.catalina.core.StandardEngine

    在tomcat8中,默认的Engine配置为:

    在这里插入图片描述

    8 Host

    Host是Engine的子容器,Engine中可以包含1个或多个Host组件,Engine组件的defaultHost属性必须与其中一个Host的name属性一致。对应着org.apache.catalina.Host接口。

    Host表示一个虚拟主机,可以包含(管理)一个或多个Web应用(Host内部的一个Context代表一个Web应用),并负责安装、展开、启动和结束每个Web应用。配置多个Host可以让一个tomcat支持从不同的域名访问Web应用。

    Host 的所有实现都支持以下常见属性:

    属性名描述
    name虚拟主机名。一般情况下,指定主机名需要是在DNS服务器中注册的网络名。localhost是DNS服务器中已经注册好的localhost对应着127.0.0.1,因此不需要我们手动注册。 如果是本地测试,Windows系统中,可以在‪C:\Windows\System32\drivers\etc\hosts文件中添加域名映射。
    appBase此虚拟主机的应用程序基础目录,这里指定目录的路径名,该目录下可能包含要在此虚拟主机上部署的 Web 应用程序。可以指定绝对路径名,也可以指定相对于tomcat基础目录的路径名。如果未指定,默认值为“webapps”。该属性主要用于Web 应用程序的自动识别和部署。
    autoDeploy指示 Tomcat 在 运行时应定期检查新的或更新的 Web 应用程序。如果为true,Tomcat 会定期检查 appBase 和 xmlBase 目录,并部署找到的任何新的 Web 应用程序或上下文 XML 描述符。更新的 Web 应用程序或上下文 XML 描述符将触发 Web 应用程序的重新加载。标志的值默认为 true。有关详细信息,请参阅自动应用程序部署。
    className指定org.apache.catalina.Host接口的实现类全路径名,默认值为org.apache.catalina.core.StandardHost
    startStopThreads此Host主机用于并行启动/发布子Context标签(Web应用)的线程数。如果开启自动部署,那么将使用同一个线程池来部署新的Web应用。指定为0,表示将使用Runtime.getRuntime().availableProcessors()数量的线程。负值将导致使用Runtime.getRuntime().availableProcessors()+startStopThreads的线程数量,如果结果小于1,在这种情况下将使用 1 个线程。如果未指定,将使用默认1个线程,用于部署Host下的所有Web项目。如果Host下的Web项目较多,由于只有一个线程负责部署这些项目,因此这些项目将依次部署,最终导致Tomcat的启动时间较长。此时,修改startStopThreads值,增加Host部署Web项目的并行线程数,可降低Tomcat的启动时间。

    Host的标准实现是org.apache.catalina.core.StandardHost,它还支持以下常见附加属性:

    属性名描述
    unpackWARs指示是否将代表Web应用的WAR文件解压;如果为true,则先解压然后运行解压的Web应用,如果为false,直接使用WAR文件运行Web应用。

    在tomcat8中,默认的Host配置为:

    在这里插入图片描述

    它表示虚拟主机名为localhost,应用程序基础目录为一个相对路径,即tomcat目录下的webapps目录,并且支持自动解压应用的War包,支持自动发布和更新项目。

    因此我们启动一个新的tomcat8,它的默认访问URL前缀应该是localhost:8080。

    8.1 Context

    Context(上下文)代表一个运行在特定虚拟主机(Host)中运行的 Web 应用程序。一个Host内可以有0个或者多个Context。

    对应着org.apache.catalina.Context接口。通过配置Context标签可以手动将其他路径的Web应用配置到tomcat中。

    Context的所有实现都支持以下常见属性:

    1. path
      1. 此 Web 应用程序的虚拟上下文路径。与每个请求 URI 的开头字符串匹配,用以选择适当 Web 应用程序来处理特定的URI。一个主机(Host)内的所有上下文(Context)路径必须是唯一的。比如某个context设置path=“test”,那么请求URI前缀为http://localhost:8080/test才能访问该应用内部的资源。
      2. 如果指定空字符串""的上下文路径,则表示该Context为此主机的默认的Web 应用程序,该应用程序将处理没有分配到其他上下文中的所有请求。
      3. 一个Host中应该有一个Context的path="",用于处理与任何其他上下文路径不匹配的所有请求。
    2. docBase
      1. 此web应用程序的物理根目录,若该路径是相对路径的话,则是相对于appBase而言,若是绝对路径,则与appBase无关。
      2. 比如指定某个Context的docBase =“test”,那么表示对应的web应用根目录为CATALINA_HOME/webapps/test
    3. reloadable
      1. 是否支持重新加载web应用程序类,默认为false。如果这个属性设为true,Tomcat服务器在运行时会监视在WEB-INF/classes和Web-INF/lib目录下的class文件的改变,如果监视到有class文件被,更改,服务器自重新加载该Web应用。
      2. 在开发环境下,reloadable设置为true便于调试;但是在生产环境中设置为true会给服务器带来性能压力,因此reloadable参数的默认值为false。
    4. cookies
      1. 是否通过Cookie来支持Session会话(这需要客户端支持Cookie),默认值为true。
    5. crossContext
      1. 如果要在此应用程序中调用 ServletContext.getContext()返回在此虚拟主机上运行的其他Web应用程序的请求调度程序,请设置为true。默认设置为 false,使 getContext()方法始终返回 null。
      2. 设置为true时,利用可以访问其他项目的ServletContext对象的特性,该Web项目的Session信息可以共享给同一host下的其他Web项目。
    6. className
      1. 指定org.apache.catalina.Context接口的实现类全路径名,默认值为org.apache.catalina.core.StandardContext。

    上下文的标准实现是org.apache.catalina.core.StandardContext。它支持以下附加常见属性:

    属性名描述
    unpackWAR指示是否将代表Web应用的WAR文件解压;如果指定为true,则通过所在Host的同名unpackWAR属性确定;如果为false,则所在Host的同名unpackWAR属性将被覆盖,并且不解包,直接使用WAR文件运行Web应用。如果未指定,则默认值为 true。
    useNaming指示是否支持JNDI,默认值为了true

    8.2 Web应用的自动部署

    tomcat可以自动部署Web应用,具体在哪里配置的呢?

    我们需要配置Host组件的deployOnStartup或者autoDeploy属性。如果deployOnStartup或者autoDeploy设置为true,则tomcat启动自动部署:当检测到新的Web应用或Web应用的更新时,会触发应用的部署或重新部署。二者的主要区别在于,deployOnStartup为true时,Tomcat在启动时检查Web应用,且检测到的所有Web应用视作新应用;autoDeploy为true时,Tomcat在运行时定期检查新的Web应用或Web应用的更新。除此之外,二者的处理相似。

    另外,还需要配置自动部署检查的目录,可以通过Host标签的appBase和xmlBase属性配置。appBase属性指定Web应用所在的目录,默认值是“webapps”,这是一个相对路径,代表Tomcat根目录下webapps文件夹。

    xmlBase属性则是指定Web应用的XML配置文件所在的目录,默认值为conf/< engine_name>/< host_name>,例如第一部分的例子中,主机localhost的xmlBase的默认值是$TOMCAT_HOME/conf/Catalina/localhost

    一个Web应用可能包括以下文件:XML配置文件,WAR包,以及一个应用目录(该目录包含Web应用的文件结构);其中XML配置文件位于xmlBase指定的目录,WAR包和应用目录位于appBase指定的目录。

    Tomcat按照如下的顺序进行扫描,来检查应用更新:

    1. 扫描虚拟主机指定的xmlBase下的XML配置文件
    2. 扫描虚拟主机指定的appBase下的WAR文件
    3. 扫描虚拟主机指定的appBase下的应用目录

    8.3 自动部署与Context

    自动部署模式下,appBase目录中的Web应用不需要配置Context,tomcat会自动扫描appBase中的WAR包和应用目录来创建Context。
    就算手动配置了Context,也不需要配置docBase和path属性。

    1. 自动部署模式下,tomcat会自动扫描appBase中的WAR包和应用目录来作为docBase属性值,如果手动指定了,返回可能会造成问题。
    2. 自动部署模式下,appBase中的Web应用不能指定path属性,path属性由配置文件的文件名、WAR文件的文件名或应用目录的名称自动推导出来。

    比如,tomcat8的webapps中的默认有一下Web应用:

    在这里插入图片描述

    我们不必要单独为它们配置Context,它们的path就是对应的项目目录名,即docs、examples、host-manager、manager。对于名称为ROOT的目录,则该Web应用看作是虚拟主机默认的Web应用,此时path属性推导为””

    因此,我们访问locahost:8080,实际上就是访问ROOT应用下的资源,而访问locahost:8080/docs,实际上就是访问docs应用下的资源。

    8.4 静态部署Web应用

    我们的项目默认都是放到webapps下面,此时称为自动部署,我们在学习了Context之后,现在可以将Web应用放在其他地方法,通过手动配置Context标签,也能让tomcat可以找到它,部署的应用称为外部应用。通过Context部署的项目称为静态部署。

    假设有一个Web应用目录为G:\work\hello,这时我们需要通过tomcat访问,那么我们可以在Server.xml中配置Context标签:

    <Context docBase="G:\work\hello" path="" reloadable="true" />
    

    reloadable属性的用法与自动部署时相同。静态部署时,也可以显式指定path属性,但是仍然受到了严格的限制:只有当自动部署完全关闭(deployOnStartup和autoDeploy都为false)或docBase不在appBase中时,才可以设置path属性。

    还有一种方法,在conf/catalana/localhost目录下创建一个hello.xml文件,在该文件中编写< Context/>标签,在标签中指明Web目录地址。

    <Context docBase="G:\work\hello"/>	
    

    此时path属性自动推导。

    9 tomcat的请求查找流程

    当请求被发送到Tomcat所在的主机时,如有多个Web应用,如何确定最终哪个Web应用来处理该请求呢?大概流程图如下:

    在这里插入图片描述

    其中index.html表示hello应用中的静态资源路径,通过该路径可以直接访问静态资源,而servlet/Aservlet则表示hi应用中的动态资源Servlet的映射路径,通过该路径可以找到对应的Servlet,随后即可处理请求。

    9.1 根据协议和端口号选定Service和Engine

    Service中的Connector组件可以接收特定端口和特定类型的请求,因此,当Tomcat启动时,Service组件就会监听特定的端口。当请求进来时,Tomcat便可以根据协议和端口号选定处理请求的Service;Service一旦选定,Engine也就确定。

    tomcat8默认的Service配置监听8080端口的HTTP请求。

    通过在Service中配置多个Connector或者在Server中配置多个Service,可以实现通过不同的端口号来访问同一台机器上部署的不同应用。

    9.2 根据域名或IP地址选定Host

    Service确定后,Tomcat在Service内部的Engine中寻找name属性值与域名/IP地址匹配的Host处理该请求。如果没有找到,则使用Engine中指定的defaultHost来处理该请求。

    tomcat8默认的Engine内部只有一个Host,name为locathost,并且defaultHost属性为locathost,因此该Service的所有请求都交给该Host处理。

    9.3 根据URI选定Context(Web应用)

    选定Host之后,用于处理每个 HTTP 请求的 Web 应用程序由 Catalina 根据将请求 URI 的最长前缀与每个Context的上下文路径path来匹配,如果与某个Context的path一致,那么表示该请求将选择该Context对应的Web应用程序来处理,如果没有与任何一个Context的path匹配成功,那么将使用path=""的Conext。

    在选择Context后,该上下文将根据对应的 Web 应用程序在部署时指定的 servlet 映射路径,选择适当的 servlet 来处理传入请求。

    参考资料:

    1. Apache Tomcat 8 Configuration Reference
    2. 深入理解-Tomcat-(二)-从宏观上理解-Tomcat-组件及架构
    3. 深度解读Tomcat中的NIO模型
    4. 详解tomcat的连接数与线程池

    如有需要交流,或者文章有误,请直接留言。另外希望点赞、收藏、关注,我将不间断更新各种Java学习博客!

    展开全文
  • 前言作为Java程序员,对于Tomcat的server.xml想必都不陌生。本文基于Tomcat7.0的Java源码,对server.xml文件是如何加载和解析进行分析。加载过程分析Bootstrap的load方法用于加载Tomcat的server.xml,实际是通过反射...

    前言

    作为Java程序员,对于Tomcat的server.xml想必都不陌生。本文基于Tomcat7.0的Java源码,对server.xml文件是如何加载和解析进行分析。

    加载过程分析

    Bootstrap的load方法用于加载Tomcat的server.xml,实际是通过反射调用Catalina的load方法,代码如下:

    /**

    * Load daemon.

    */

    private void load(String[] arguments)

    throws Exception {

    // Call the load() method

    String methodName = "load";

    Object param[];

    Class> paramTypes[];

    if (arguments==null || arguments.length==0) {

    paramTypes = null;

    param = null;

    } else {

    paramTypes = new Class[1];

    paramTypes[0] = arguments.getClass();

    param = new Object[1];

    param[0] = arguments;

    }

    Method method =

    catalinaDaemon.getClass().getMethod(methodName, paramTypes);

    if (log.isDebugEnabled())

    log.debug("Calling startup class " + method);

    method.invoke(catalinaDaemon, param);

    Catalina的load方法实现如下:

    /**

    * Start a new server instance.

    */

    public void load() {

    if (loaded) {

    return;

    }

    loaded = true;

    long t1 = System.nanoTime();

    initDirs();

    // Before digester - it may be needed

    initNaming();

    // Create and execute our Digester

    Digester digester = createStartDigester();

    InputSource inputSource = null;

    InputStream inputStream = null;

    File file = null;

    try {

    try {

    file = configFile();

    inputStream = new FileInputStream(file);

    inputSource = new InputSource(file.toURI().toURL().toString());

    } catch (Exception e) {

    if (log.isDebugEnabled()) {

    log.debug(sm.getString("catalina.configFail", file), e);

    }

    }

    if (inputStream == null) {

    try {

    inputStream = getClass().getClassLoader()

    .getResourceAsStream(getConfigFile());

    inputSource = new InputSource

    (getClass().getClassLoader()

    .getResource(getConfigFile()).toString());

    } catch (Exception e) {

    if (log.isDebugEnabled()) {

    log.debug(sm.getString("catalina.configFail",

    getConfigFile()), e);

    }

    }

    }

    // This should be included in catalina.jar

    // Alternative: don't bother with xml, just create it manually.

    if( inputStream==null ) {

    try {

    inputStream = getClass().getClassLoader()

    .getResourceAsStream("server-embed.xml");

    inputSource = new InputSource

    (getClass().getClassLoader()

    .getResource("server-embed.xml").toString());

    } catch (Exception e) {

    if (log.isDebugEnabled()) {

    log.debug(sm.getString("catalina.configFail",

    "server-embed.xml"), e);

    }

    }

    }

    if (inputStream == null || inputSource == null) {

    if (file == null) {

    log.warn(sm.getString("catalina.configFail",

    getConfigFile() + "] or [server-embed.xml]"));

    } else {

    log.warn(sm.getString("catalina.configFail",

    file.getAbsolutePath()));

    if (file.exists() && !file.canRead()) {

    log.warn("Permissions incorrect, read permission is not allowed on the file.");

    }

    }

    return;

    }

    try {

    inputSource.setByteStream(inputStream);

    digester.push(this);

    digester.parse(inputSource);

    } catch (SAXParseException spe) {

    log.warn("Catalina.start using " + getConfigFile() + ": " +

    spe.getMessage());

    return;

    } catch (Exception e) {

    log.warn("Catalina.start using " + getConfigFile() + ": " , e);

    return;

    }

    } finally {

    if (inputStream != null) {

    try {

    inputStream.close();

    } catch (IOException e) {

    // Ignore

    }

    }

    }

    getServer().setCatalina(this);

    // Stream redirection

    initStreams();

    // Start the new server

    try {

    getServer().init();

    } catch (LifecycleException e) {

    if (Boolean.getBoolean("org.apache.catalina.startup.EXIT_ON_INIT_FAILURE")) {

    throw new java.lang.Error(e);

    } else {

    log.error("Catalina.start", e);

    }

    }

    long t2 = System.nanoTime();

    if(log.isInfoEnabled()) {

    log.info("Initialization processed in " + ((t2 - t1) / 1000000) + " ms");

    }

    }

    上面代码看起来东西挺多,把注释、异常抛出、记录日志、流关闭、非空判断这些放在一边就会发现实际上真正做事的就这么几行代码:

    Digester digester = createStartDigester();

    inputSource.setByteStream(inputStream);

    digester.push(this);

    digester.parse(inputSource);

    getServer().setCatalina(this);

    getServer().init();

    做的事情就两个,一是创建一个 Digester 对象,将当前对象压入 Digester 里的对象栈顶,根据 inputSource 里设置的文件 xml 路径及所创建的 Digester 对象所包含的解析规则生成相应对象,并调用相应方法将对象之间关联起来。二是调用 Server 接口对象的 init 方法。

    这里碰到了 Digester,有必要介绍一下 Digester 的一些基础知识。一般来说 Java 里解析 xml 文件有两种方式:一种是 Dom4J 之类将文件全部读取到内存中,在内存里构造一棵 Dom 树的方式来解析。一种是 SAX 的读取文件流,在流中碰到相应的xml节点触发相应的节点事件回调相应方法,基于事件的解析方式,优点是不需要先将文件全部读取到内存中。

    Digester 本身是采用 SAX 的解析方式,在其上提供了一层包装,对于使用者更简便友好罢了。最早是在 struts 1 里面用的,后来独立出来成为 apache 的 Commons 下面的一个单独的子项目。Tomcat 里又把它又封装了一层,为了描述方便,直接拿 Tomcat 里的 Digester 建一个单独的 Digester 的例子来介绍。

    1 package org.study.digester;

    2

    3 import java.io.IOException;

    4 import java.io.InputStream;

    5 import java.util.ArrayList;

    6 import java.util.HashMap;

    7 import java.util.List;

    8

    9 import junit.framework.Assert;

    10

    11 import org.apache.tomcat.util.digester.Digester;

    12 import org.xml.sax.InputSource;

    13

    14 public class MyDigester {

    15

    16 private MyServer myServer;

    17

    18 public MyServer getMyServer() {

    19 return myServer;

    20 }

    21

    22 public void setMyServer(MyServer myServer) {

    23 this.myServer = myServer;

    24 }

    25

    26 private Digester createStartDigester() {

    27 // 实例化一个Digester对象

    28 Digester digester = new Digester();

    29

    30 // 设置为false表示解析xml时不需要进行DTD的规则校验

    31 digester.setValidating(false);

    32

    33 // 是否进行节点设置规则校验,如果xml中相应节点没有设置解析规则会在控制台显示提示信息

    34 digester.setRulesValidation(true);

    35

    36 // 将xml节点中的className作为假属性,不必调用默认的setter方法(一般的节点属性在解析时将会以属性值作为入参调用该节点相应对象的setter方法,而className属性的作用是提示解析器用该属性的值来实例化对象)

    37 HashMap, List> fakeAttributes = new HashMap, List>();

    38 ArrayList attrs = new ArrayList();

    39 attrs.add("className");

    40 fakeAttributes.put(Object.class, attrs);

    41 digester.setFakeAttributes(fakeAttributes);

    42

    43 // addObjectCreate方法的意思是碰到xml文件中的Server节点则创建一个MyStandardServer对象

    44 digester.addObjectCreate("Server",

    45 "org.study.digester.MyStandardServer", "className");

    46 // 根据Server节点中的属性信息调用相应属性的setter方法,以上面的xml文件为例则会调用setPort、setShutdown方法,入参分别是8005、SHUTDOWN

    47 digester.addSetProperties("Server");

    48 // 将Server节点对应的对象作为入参调用栈顶对象的setMyServer方法,这里的栈顶对象即下面的digester.push方法所设置的当前类的对象this,就是说调用MyDigester类的setMyServer方法

    49 digester.addSetNext("Server", "setMyServer",

    50 "org.study.digester.MyServer");

    51

    52 // 碰到xml的Server节点下的Listener节点时取className属性的值作为实例化类实例化一个对象

    53 digester.addObjectCreate("Server/Listener", null, "className");

    54 digester.addSetProperties("Server/Listener");

    55 digester.addSetNext("Server/Listener", "addLifecycleListener",

    56 "org.apache.catalina.LifecycleListener");

    57

    58 digester.addObjectCreate("Server/Service",

    59 "org.study.digester.MyStandardService", "className");

    60 digester.addSetProperties("Server/Service");

    61 digester.addSetNext("Server/Service", "addMyService",

    62 "org.study.digester.MyService");

    63

    64 digester.addObjectCreate("Server/Service/Listener", null, "className");

    65 digester.addSetProperties("Server/Service/Listener");

    66 digester.addSetNext("Server/Service/Listener", "addLifecycleListener",

    67 "org.apache.catalina.LifecycleListener");

    68 return digester;

    69 }

    70

    71 public MyDigester() {

    72 Digester digester = createStartDigester();

    73

    74 InputSource inputSource = null;

    75 InputStream inputStream = null;

    76 try {

    77 String configFile = "myServer.xml";

    78 inputStream = getClass().getClassLoader().getResourceAsStream(

    79 configFile);

    80 inputSource = new InputSource(getClass().getClassLoader()

    81 .getResource(configFile).toString());

    82

    83 inputSource.setByteStream(inputStream);

    84 digester.push(this);

    85 digester.parse(inputSource);

    86 } catch (Exception e) {

    87 e.printStackTrace();

    88 } finally {

    89 try {

    90 inputStream.close();

    91 } catch (IOException e) {

    92 // Ignore

    93 }

    94 }

    95

    96 getMyServer().setMyDigester(this);

    97 }

    98

    99 public static void main(String[] agrs) {

    100 MyDigester md = new MyDigester();

    101 Assert.assertNotNull(md.getMyServer());

    102 }

    103 }

    上面是拿 Tomcat 里的 Digester 的工具类解析 xml 文件的例子,关键方法的调用含义已经在注释中写明,解析的是项目源文件发布的根目录下的 myServer.xml 文件

    Digester 的使用一般来说有4步:

    实例化一个 Digester 对象,并在对象里设置相应的节点解析规则。

    设置要解析的文件作为输入源( InputSource ),这里 InputSource 与 SAX 里的一样,用以表示一个 xml 实体。

    将当前对象压入栈。

    调用 Digester 的 parse 方法解析 xml,生成相应的对象。

    第 3 步中将当前对象压入栈中的作用是可以保存一个到 Digester 生成的一系列对象直接的引用,方便后续使用而已,所以不必是当前对象,只要有一个地方存放这个引用即可。

    这里有必要说明的是很多文章里按照代码顺序来描述 Digester 的所谓栈模型来讲述 addSetNext 方法时的调用对象,实际上我的理解 addSetNext 方法具体哪个调用对象与XML文件里的节点树形结构相关,当前节点的父节点是哪个对象该对象就是调用对象。可以试验一下把这里的代码顺序打乱仍然可以按规则解析出来,createStartDigester 方法只是在定义解析规则,具体解析与 addObjectCreate、addSetProperties、addSetNext 这些方法的调用顺序无关。Digester 自己内部在解析 xml 的节点元素时增加了一个 rule 的概念,addObjectCreate、addSetProperties、addSetNext 这些方法内部实际上是在添加 rule,在最后解析 xml 时将会根据读取到的节点匹配相应节点路径下的 rule,调用内部的方法。关于 Tomcat 内的 Digester 的解析原理以后可以单独写篇文章分析一下。

    该示例的代码在附件中,将其放入 tomcat 7 的源代码环境中即可直接运行。

    看懂了上面的例子 Catalina 的 createStartDigester 方法应该就可以看懂了,它只是比示例要处理的节点类型更多,并且增加几个自定义的解析规则,如 384 行在碰到 Server/GlobalNamingResources/ 节点时将会调用 org.apache.catalina.startup.NamingRuleSet 类中的 addRuleInstances 方法添加解析规则。

    要解析的 XML 文件默认会先找 conf/server.xml,如果当前项目找不到则通过其他路径找 xml 文件来解析,这里以默认情况为例将会解析 server.xml

    type="org.apache.catalina.UserDatabase"

    description="User database that can be updated and saved"

    factory="org.apache.catalina.users.MemoryUserDatabaseFactory"

    pathname="conf/tomcat-users.xml" />

    connectionTimeout="20000"

    redirectPort="8443" />

    resourceName="UserDatabase"/>

    unpackWARs="true" autoDeploy="true">

    prefix="localhost_access_log." suffix=".txt"

    pattern="%h %l %u %t "%r" %s %b" />

    这样经过对 xml 文件的解析将会产生 org.apache.catalina.core.StandardServer、org.apache.catalina.core.StandardService、org.apache.catalina.connector.Connector、org.apache.catalina.core.StandardEngine、org.apache.catalina.core.StandardHost、org.apache.catalina.core.StandardContext 等等一系列对象,这些对象从前到后前一个包含后一个对象的引用(一对一或一对多的关系)。

    解析完 xml 之后关闭文件流,接着设置 StandardServer 对象(该对象在上面解析 xml 时)的 catalina 的引用为当前对象,这种对象间的双向引用在 Tomcat 的很多地方都会碰到。

    接下来将调用 StandardServer 对象的 init 方法。

    上面分析的是 Catalina 的 load 方法,上一篇文章里看到 Bootstrap 类启动时还会调用 Catalina 对象的 start 方法,代码如下:

    /**

    * Start a new server instance.

    */

    public void start() {

    if (getServer() == null) {

    load();

    }

    if (getServer() == null) {

    log.fatal("Cannot start server. Server instance is not configured.");

    return;

    }

    long t1 = System.nanoTime();

    // Start the new server

    try {

    getServer().start();

    } catch (LifecycleException e) {

    log.fatal(sm.getString("catalina.serverStartFail"), e);

    try {

    getServer().destroy();

    } catch (LifecycleException e1) {

    log.debug("destroy() failed for failed Server ", e1);

    }

    return;

    }

    long t2 = System.nanoTime();

    if(log.isInfoEnabled()) {

    log.info("Server startup in " + ((t2 - t1) / 1000000) + " ms");

    }

    // Register shutdown hook

    if (useShutdownHook) {

    if (shutdownHook == null) {

    shutdownHook = new CatalinaShutdownHook();

    }

    Runtime.getRuntime().addShutdownHook(shutdownHook);

    // If JULI is being used, disable JULI's shutdown hook since

    // shutdown hooks run in parallel and log messages may be lost

    // if JULI's hook completes before the CatalinaShutdownHook()

    LogManager logManager = LogManager.getLogManager();

    if (logManager instanceof ClassLoaderLogManager) {

    ((ClassLoaderLogManager) logManager).setUseShutdownHook(

    false);

    }

    }

    if (await) {

    await();

    stop();

    }

    }

    这里最主要的是调用 StandardServer 对象的 start 方法。

    经过以上分析发现,在解析 xml 产生相应一系列对象后会顺序调用 StandardServer 对象的 init、start 方法,这里将会涉及到 Tomcat 的容器生命周期( Lifecycle ),关于这点留到下一篇文章中分析。

    展开全文
  • xml version="1.0" encoding="UTF-8"?> <!-- Server 根元素,创建⼀个Server实例,⼦标签有 Listener、GlobalNamingResources、Service port:关闭服务器的监听端⼝ shutdown:关闭服务器的指令字符串 -...
  • /bin/bashecho -e '\n'echo "***********************************"port1=`grep -r "shutdown" server.xml|awk 'BEGIN {FS="\" "} {print $1}'|awk -F"\"" '{print $2}'`echo -e 当前Tomcat的监听端口为:"\033[32m ...
  • In our project, we have implemented SOAP webservices using Apache CXF ... Clients used to request the server for some command execution. The request consists of host, port and the protocol used...
  • xml version='1.0' encoding='utf-8'?> <Server port="8005" shutdown="SHUTDOWN"> <!-- 启动时记录tomcat服务器的版本信息、操作系统信息、jdk相关信息等--> <Listener className="org....
  • xml version="1.0" encoding="UTF-8"?> <!--The connectors can use a shared executor, you can define one or more named thread pools--> <!-- <Executor name=...
  • 概括:Tomcat启动时,先找系统变量CATALINA_BASE,如果没有,则找...要配置tomcat,基本上了解server.xml,context.xml和web.xml。能在别的配置文件中配置的内容不推荐在server.xml中进行配置,如:能在/conf/cont...
  • 配置Tomcat时server.xml自动还原问题【Tomcat会删除自己在Servlet.xml 配置的Context元素】
  • 有时候需要在tomcat里面做特殊的配置,来进行访问:例如你的程序 名字是hello端口是80 ...就需要进行tomcat 的配置了呢看以下配置:tomcat里面conf 里的server.xml 最下面unpackWARs="true" autoDeploy="true"xmlVa...
  • 如果要连接到mysql数据库并希望 manually 在server.xml中提供凭据,则可以执行以下操作:server.xml中:URL="jdbc:mysql://1.2.3.4:3306/db"password="mypassword" user="admin" />name="MySQL Connector">...
  • 之前由于一直在Windows服务器下进行操作,部署环境、开启应用及代码调试,Tomcat的配置文件server.xml都是以Windows系统下的配置为准,但是当把Tomcat部署到应用服务上时,设置server.xml的context时,开启Tomcat...
  • 场景:同一服务器上,部署启动两个Tomcat。Tomcat安装和配置环境变量跳过。 两个Tomcat同时启动,需更改端口。 如图: 保存后,启动两个Tomcat,如图: OVER!!!
  • 在tomcat的server.xml中有这么几个port,很多人虽然一直在使用tomcat,但是却不知道这几个port各有什么作用,今天博主就来简单说说她们的作用和区别,先上一段代码片段: 1.<Server port="8005" shutdown="SHUTDOWN...
  • 1,在server.xml文件中加入如下内容,也就是说,当请求的url中包含upload,这个upload就会被自动解析成:C:\Users\twf\Pictures\o2o\image\upload。 我的图片是放在本地:C:\Users\twf\Pictures\o2o\image\upload...
  • 需要做图片上传功能,第一次使用的路径是项目路径下的资源路径。发现每次上传成功后并不能直接使用url访问,只能重新服务才能访问。后来百度得知需要放到其他硬盘地方。需要用tomcat做服务器来存储图片。...
  • 在tomcat的配置文件server.xml中,可以设置Connector的参数,其中包含超时参数connectionTimeout。本人对其中几个重要参数大致理解为(应该理解错了):connectionTimeout:一个请求最多等待时间,超过则报错。max...
  • 上篇文章我们介绍到,在Catalina的load方法中,完成了server.xml的解析,将server.xml配置的Server、Service、Connector、Engine、Host各组件实例化,并维护父子级关系。本篇文章我们来看一下server.xml是如何解析的...
  • 今天,因为工作需要,所以在一个windows环境中配置了两个tomcat,但是第二个tomcat一直报如题目所示的错误,网上百度和google搜索出来的结果都是端口占用、修改配置等,而我仔细看了看问题所在,后面标有如下图所示...
  • 一、修改tomcat的配置文件server.xml    首先修改一下tomcat的配置,找到tomcat安装目录下的conf文件夹,打开server.xml配置文件,配置方法如下图:    修改配置后重启tomcat,查看路径文件,发现配置的虚拟...
  • 规划:网站网页目录:/web/www 域名:www.test1.com论坛网页目录:/web/bbs URL:bbs.test1.com/bbs网站管理程序:$CATALINA_HOME/wabapps URL:manager.test.com 允许访问地址:172.23.136.*conf/server....
  • 一、修改Server.xml文件  在conf下的server.xml文件里找到Host标签,在里面添加如下代码: <Context path="/jfinal_demo" docBase="F:\work\jfinal_demo\WebRoot" reloadable="true" debug="0" ...
  • 如上图,server.xml中一个Host下的Contex配置签即配置了一个虚拟目录。 若想在浏览器中查看该目录所有文件,则需配置web.xml
  • 理解Tomcat 的配置文件 server.xml Tomcat 的配置文件 server.xml结构:...Server:根元素,表示整个服务器的配置信息。Service:它表示服务,在 中只能有一个Service元素。Connector:它表示连接,在 中可以有N个...
  • tomcat中server.xml配置详解 这篇博客从理论和基本元素出发,讲解的很详细,值得参考。 https://blog.csdn.net/qq_31957747/article/details/53729530 tomcat配置文件server.xml含义说明 这篇文章对应conf中server....
  • vs2019 新建ADO.NET 实体数据模型,新建连接填写完数据库服务器名称并且选择数据库,点击完成后报错 make sure microsoft.visualstudio.data.providers.sqlserver.sqlviewsupport.xml... ,如下图(已经解决无法还原...
  • 解决Error running 'Tomcat(备注这里你起的名字)': SSL HTTP Connector node not found: set up one in the server.xml
  • Tomcat配置文件Server.xml解析一 核心的解析逻辑1.1 parseServerXml二 XML文件解析方法2.1 预加载DOM树2.2 事件机制的SAX三 Digester3.1 Digester基本架构3.2 Digester解析XML文档的流程3.3 使用流程四 Digester解析...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 896,427
精华内容 358,570
关键字:

server.xml