【问题标题】:How to set tomcat work at debug mode?如何设置tomcat在调试模式下工作?
【发布时间】:2011-11-14 17:14:21
【问题描述】:

我使用上下文 xml 将应用程序部署到 tomcat。我希望 tomcat 在调试模式下工作,我的意思是如果我更改函数内部的某些内容,例如更改 字符串 a="123"; 到 字符串 a="456"; tomcat 应该在不重新加载应用程序的情况下获得更改。

%CATALINA_HOME%/conf/Catalina/localhost下的web01.xml

<?xml version='1.0' encoding='utf-8'?>
<Context docBase="d:/document/workspace3.6/web01/WebContent" path="/web01" reloadable="false" debug="1" ></Context>

但是现在tomcat没有像我预期的那样工作,如果我用新版本替换旧的类文件,我必须重新启动tomcat才能得到改变。

为什么tomcat没有重新加载类,我该怎么做才能让它在调试模式下工作?

我现在不使用 Eclipse。而且我不想设置 reloadable="true",如果类更改,这将重新加载整个应用程序。

我用的是tomcat5.5.23

【问题讨论】:

    标签: java tomcat tomcat5.5


    【解决方案1】:

    好的,这是一个实际的例子:

    我有cnas-war maven 项目。一旦我用 Maven 构建它,我会得到以下目录:

    c:/_andrei/work/cnas/cnas-war/target\cnas-war-0.0.1-SNAPSHOT
    

    在这里,我拥有通​​常会打包在 .war 文件中的所有内容,例如 .class 文件、.jsp 文件、.jar 文件等。实际上,它是 .war 文件的分解。

    我也有一个Tomcat 5.5 专门为这个war 的部署量身定做的,巧妙的放在tomcat_cnas 文件夹下。在 Tomcat 配置文件 (conf\server.xml) 我有以下内容:

        <?xml version="1.0" encoding="utf-8"?>
    <!-- Example Server Configuration File -->
    <!-- Note that component elements are nested corresponding to their
         parent-child relationships with each other -->
    <!-- A "Server" is a singleton element that represents the entire JVM,
         which may contain one or more "Service" instances.  The Server
         listens for a shutdown command on the indicated port.
    
         Note:  A "Server" is not itself a "Container", so you may not
         define subcomponents such as "Valves" or "Loggers" at this level.
     -->
    <Server port="8125" shutdown="SHUTDOWN">
      <!-- Comment these entries out to disable JMX MBeans support used for the 
           administration web application 
      <Listener className="org.apache.catalina.core.AprLifecycleListener" />
      <Listener className="org.apache.catalina.storeconfig.StoreConfigLifecycleListener"/> -->
      <Listener className="org.apache.catalina.mbeans.ServerLifecycleListener" />
      <Listener className="org.apache.catalina.mbeans.GlobalResourcesLifecycleListener" />
      <!-- Global JNDI resources -->
      <GlobalNamingResources>
        <!-- Test entry for demonstration purposes -->
        <Environment name="simpleValue" type="java.lang.Integer"
        value="30" />
        <Resource auth="Container"
        configurationDirectory="c:/cnas-content"
        factory="com.genia.toolbox.web.jndi_config.StringContainerFactory"
        name="string/activitymanagerConfigurationContainer"
        type="com.genia.toolbox.web.jndi_config.StringContainer" />
        <Resource name="string/activitymanagerConfigurationContainer"
        auth="Container"
        type="com.genia.toolbox.web.jndi_config.StringContainer"
        factory="com.genia.toolbox.web.jndi_config.StringContainerFactory"
        configurationDirectory="c:/cnas-content" />
      </GlobalNamingResources>
      <!-- Define the Tomcat Stand-Alone Service -->
      <Service name="Catalina">
        <!-- Define a non-SSL HTTP/1.1 Connector on port 8080 -->
        <Connector acceptCount="100" connectionTimeout="20000"
        disableUploadTimeout="true" enableLookups="false"
        maxHttpHeaderSize="8192" maxSpareThreads="75" maxThreads="150"
        minSpareThreads="25" port="8081" redirectPort="8443" />
        <!-- Define the top level container in our container hierarchy -->
        <Engine defaultHost="localhost" name="Catalina">
          <!-- for activitymanager -->
          <Host name="localhost" appBase="webapps" unpackWARs="true"
          autoDeploy="true" xmlValidation="false"
          xmlNamespaceAware="false">
            <Context path="/cnas"
            docBase="c:/_andrei/work/cnas/cnas-war/target/cnas-war-0.0.1-SNAPSHOT/"
            workDir="c:/_andrei/work/cnas/cnas-war/target/work-cnas/">
              <ResourceLink name="string/configurationContainer"
              global="string/activitymanagerConfigurationContainer"
              type="com.genia.toolbox.web.jndi_config.StringContainer" />
              <Resource name="bean/cnasConfig" auth="Container"
              type="com.genia.toolbox.projects.cnas.war.config.CnasConfig"
              factory="org.apache.naming.factory.BeanFactory"
              classpath="false" fileSystem="true"
              applicationFileLocation="c:/cnas-content/application.properties" />
              <Resource name="bean/cnasApplicationData"
              auth="Container"
              type="com.genia.toolbox.projects.cnas.war.config.CnasConfig"
              factory="org.apache.naming.factory.BeanFactory"
              classpath="false" fileSystem="true"
              applicationFileLocation="c:/cnas-content/cnas_application_data.xml" />
            </Context>
            <!--Context docBase="C:/travail/workspace/cnas/cnas-ws-proxy/target/webapp" path="/proxy">
    
                    <Resource name="bean/params" 
                        auth="Container"
                        type="fr.genia.cnas.config.Parameters" 
                        factory="org.apache.naming.factory.BeanFactory"
                        log4jFile="" 
                        serviceUrl="" 
                        debugMode="true" >
    
                    </Resource>
    
                </Context-->
          </Host>
        </Engine>
      </Service>
    </Server>
    

    如您所见,在“context”标签中,我有一个 docBase 属性指向快照目录(在 maven 构建后战争爆发的那个目录)。现在,有了这个设置,并将这个项目导入 Eclipse,如果我进行 maven 构建,然后启动这个 Tomcat,war 将被部署并运行。此时,如果我在 Eclipse 中修改 .java 文件中的方法内容(并保存),那么 Tomcat 将自动考虑该代码,并且应用程序的行为将有所不同,无需任何额外的重新部署。希望这会有所帮助

    【讨论】:

    • 感谢您的示例,如果我从 eclipse 启动它,我的 tomcat 可以执行热代码替换,但现在我不能使用 eclipse,我想知道如何将 tomcat 配置为热替换启动时使用startup.bat文件。
    • 在上面的例子中,tomcat 从未在 eclipse 中配置,它是单独启动的(如果你愿意,可以使用 startup.bat)。 Eclipse 与 tomcat 内部的热部署没有任何关系(它通过其 tomcat 连接器促进它,但这不是强制性的)。
    【解决方案2】:

    要做你想做的事,你需要java rebel之类的东西或类似的东西我知道有一些开源alternatives可以做同样的事情。

    【讨论】:

      【解决方案3】:

      您实际上混淆了“调试”和热部署的概念。您可以将 Tomcat 配置为调试模式,然后远程调试在 tomcat 中运行的应用程序,这样当您在代码中添加断点时,调试器将跳转到该断点并停止执行。

      您真正需要的是能够热部署应用程序。使用 tomcat,如果您修改 .java 文件,然后将它们复制到 tomcat 的工作目录,您将得到您想要的,即能够更改类中的某些内容并让运行的 tomcat 部署的应用程序将其纳入帐户,而无需重新部署整个应用程序。您可以通过为您的应用程序配置您的 tomcat 应用程序上下文(在 tomcat server.xml 文件或项目特定的 context.xml 文件中)以将编译项目代码的目录作为工作目录来自动执行此操作。

      这是一个实际的例子:

      假设您在目录 c:\myProject 中有一个 maven 项目。您将在 c:\myProject\src 中有源文件,然后在编译它时,您将分别在 c:\myProject\target\myProject.war 和c:\我的项目\目标\我的项目。现在,如果您配置您的 tomcat,以便为 myProject tomcat 上下文配置工作目录,则您将工作目录配置为 c:\myProject\target\myProject,然后每次修改 .java 文件时,.class 对应文件将在目标(现在也在工作)目录,tomcat 会考虑它。

      我实际上使用过这样的设置来使用tomcat进行开发,但这并不是最好的。首先,tomcat 将仅热部署某些修改,例如当您修改现有方法主体中的某些内容时。其他修改将不予考虑,例如添加新方法 - 为此您必须进行完全重新部署才能将其考虑在内。

      更好的解决方案是将 maven 与 maven jetty 插件一起使用。这件事真的如你所愿:你对一类 jsp 文件所做的任何修改都会立即被考虑在内,并且在 jetty 内正在运行的应用程序中可见。

      【讨论】:

      • 是的,我想要的是热代码替换,我只是希望tomcat可以在我修改现有方法体中的某些内容时替换代码。但它没有用。我在我的配置文件中犯了一些错误吗?
      【解决方案4】:
      猜你喜欢
      • 2014-08-17
      • 2019-07-17
      • 2018-05-02
      • 2014-12-09
      • 2021-10-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多