JDBC Transport Examples

本文详细介绍了 Mule Enterprise JDBC 运输的实例运行,包括设置、使用批处理插入加载 CSV 文件到数据库、同步查询数据库生成 XML 报告、调用存储过程克隆数据、批量迁移数据以及数据清理等步骤。

This page describes the examples you can run for the Mule Enterprise JDBC transport. These examples are designed to work with Oracle databases only.

Setup

The Mule Enterprise JDBC Examples are located in your installation at $MULE_HOME/examples/jdbc.

1. Before running any examples, do the following:

  • Run the statements in scripts/tables.ddl to create tables in your favorite database.
  • Edit the conf/db.properties file with your database connection configuration.
  • Copy your database driver to your $MULE_HOME/lib/user directory.

2. Run the examples using the "jdbc.bat" or "jdbc" shell script provided in this directory. After running the script, you will see the following:

$ ./jdbc.bat
Examples require that you set up your database first. See README for more details.
After your database is set up, choose one of the following examples to run:
1. Mules are born.  Read in 50 baby mules from a CSV File and create records in mule_source table.
2. View Mules.  Generate an XML report of Mules.  (http://localhost:8080/first20)
3. Clone Mules.  Clone mules using a Stored Procedure. (http://localhost:8080/clone)
4. Retire Mules.  Send mules to a retirement ranch (a.k.a the mule_target table).
5. Cleanup Mules.  Reset tables to run examples again (http://localhost:8080/cleanup).
Select the one you wish to execute and press Enter...

3. Choose the number of the Example you want to run.

The examples are designed to be run in order.

Example 1 - Mules Are Born

This example loads records from a CSV file to the database. The CSV file ("data/mules.csv") contains information about 50 baby mules born at various local ranches. The goal is to upload these records into a database table called "mule_source".

Configuration

See conf/jdbc-csv.xml

Features Used

This example uses the CSV Transformer to convert the CSV file into JDBC-format Maps and inserts these records into the database using a batch INSERT.

Running the Example

To run the example, choose option "1" after starting the Mule server. When the server starts, Mule will immediately load all the records.

To verify that the example loaded correctly, use your favorite database tool to see that there were 50 records inserted into the mule_source table.

SQL> select count(1) from mule_source;

COUNT(1)
----------
50

If you want to run the example again, first delete the records from mule_source.

Example 2 - See the Baby Mules

This example displays the mule records loaded into the database in Example 1.

Configuration

See conf/jdbc-xml-report.xml

Features Used

This example uses an outbound SELECT query to synchronously query the database. The results are transformed into XML using the XML transformer.

Running the Example

Start the Mule server and choose Example 2. Then, enter the URL http://localhost:8080/first20 into your web browser. You should see the first 20 mule records presented in XML format.

Example 3 - Mule Cloning

The following example assumes that you are using an Oracle database. However, you can adapt the stored procedure for other database platforms.

This example shows how to invoke a stored procedure in Mule. This particular stored procedure clones the records in the mule_source database (doubling the size of the table each time it is run). The goal is to create a large dataset that we can use in Example 4.

Configuration

See conf/jdbc-stored-procedure.xml

Features Used

This page uses an outbound SELECT query and stored procedure support to synchronously call a stored procedure.

Running the Example

Before running this example, run the statements in the scripts/oracle_procs.ddl to create the stored procedure and sequence.

Start the Mule server and choose Example 3. Then, enter the URL http://localhost:8080/clone into your web browser. You should see the current count of the number of mules in mule_source. Each time you refresh the page, the number of mules should double. Try refreshing several times until there are thousands or even millions of mules or more in the table. The mules multiply quickly!

Example 4 - Mass Mule Retirement

This example retires all our mules by transferring them from one database table (mule_source) to another (mule_target). We can think of this as a simple ETL use case.

Configuration

See conf/jdbc-etl.xml

Features Used

This page uses large dataset retrieval, an outbound SELECT query, and batch INSERT statements to transfer arbitrarily large numbers of records from one table another.

Running the Example

Before running this example, you can optionally change the location of the ID store in jdbc-etl.xml:

    <spring:bean id="idStore" class="org.mule.transport.jdbc.util.IdStore">
        <spring:property name="fileName" value="/tmp/eg-batches.txt"/>
    </spring:bean>

The default location is /tmp/eg-batches.txt on Linux/Unix and c:/tmp/eg-batches.txt on Windows.

Next, for better visibility into batch activity, add the following line to your log4j.properties file (in $MULE_HOME/conf):

log4j.logger.org.mule.providers.jdbc.components=DEBUG

Finally, start the server and choose Example 4. You should see the batches of records being processed in the logs:

DEBUG 2008-04-10 20:20:03,625 \[next_batch.2\] org.mule.transport.jdbc.components.BatchManager: Processing next batch
DEBUG 2008-04-10 20:20:03,625 \[next_batch.2\] org.mule.transport.jdbc.components.BatchManager: Next range: {lowerId=1, upperId=3000}
DEBUG 2008-04-10 20:20:04,531 \[next_batch.2\] org.mule.transport.jdbc.components.BatchManager: Processing next batch
DEBUG 2008-04-10 20:20:04,531 \[next_batch.2\] org.mule.transport.jdbc.components.BatchManager: Next range: {lowerId=3001, upperId=6000}
DEBUG 2008-04-10 20:20:05,531 \[next_batch.2\] org.mule.transport.jdbc.components.BatchManager: Processing next batch
DEBUG 2008-04-10 20:20:05,531 \[next_batch.2\] org.mule.transport.jdbc.components.BatchManager: Next range: {lowerId=6001, upperId=9000}

In this example, batches are configured to occur every 1 second, with a batch size of 3000.

Note that if you stop and restart the Mule server, the batches should resume processing where they left off.

Re-running the Examples

If you want to run these examples again, just delete all records from both mule_source and mule_target tables, and remove the file "/tmp/eg-batches.txt". In Oracle, this may be most efficiently done by using truncate, e.g. truncate table mule_source.

Alternatively, if on Oracle, start the server choose "Example 5" to cleanup the tables mule_source and mule_target. You still need to manually remove the file "/tmp/eg-batches.txt".

------------------------ catalina.2025-06-26.log ------------------------ 26-Jun-2025 11:48:04.128 信息 [Thread-4] org.apache.coyote.AbstractProtocol.pause 暂停ProtocolHandler["http-nio-8080"] 26-Jun-2025 11:48:04.184 信息 [Thread-4] org.apache.catalina.core.StandardService.stopInternal 正在停止服务[Catalina] 26-Jun-2025 11:48:04.246 信息 [Thread-4] org.apache.coyote.AbstractProtocol.stop 正在停止ProtocolHandler ["http-nio-8080"] 26-Jun-2025 11:48:04.251 信息 [Thread-4] org.apache.coyote.AbstractProtocol.destroy 正在摧毁协议处理器 ["http-nio-8080"] 26-Jun-2025 11:48:04.268 警告 [Thread-4] org.apache.catalina.loader.WebappClassLoaderBase.clearReferencesJdbc Web应用程序 [KuCun2] 注册了JDBC驱动程序 [com.mysql.cj.jdbc.Driver],但在Web应用程序停止时无法注销它。 为防止内存泄漏,JDBC驱动程序已被强制取消注册。 26-Jun-2025 11:48:04.276 警告 [Thread-4] org.apache.catalina.loader.WebappClassLoaderBase.clearReferencesThreads Web应用程序[KuCun2]似乎启动了一个名为[mysql-cj-abandoned-connection-cleanup]的线程,但未能停止它。这很可能会造成内存泄漏。线程的堆栈跟踪:[ java.base@11/java.lang.Object.wait(Native Method) java.base@11/java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:155) com.mysql.cj.jdbc.AbandonedConnectionCleanupThread.run(AbandonedConnectionCleanupThread.java:91) java.base@11/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128) java.base@11/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628) java.base@11/java.lang.Thread.run(Thread.java:834)] 26-Jun-2025 11:48:55.666 警告 [main] org.apache.catalina.core.AprLifecycleListener.init 基于APR的本地库加载失败.错误报告为[D:\apache-tomcat-9.0.37\bin\tcnative-1.dll: Can't load IA 32-bit .dll on a AMD 64-bit platform] java.lang.UnsatisfiedLinkError: D:\apache-tomcat-9.0.37\bin\tcnative-1.dll: Can't load IA 32-bit .dll on a AMD 64-bit platform at java.base/java.lang.ClassLoader$NativeLibrary.load0(Native Method) at java.base/java.lang.ClassLoader$NativeLibrary.load(ClassLoader.java:2430) at java.base/java.lang.ClassLoader$NativeLibrary.loadLibrary(ClassLoader.java:2487) at java.base/java.lang.ClassLoader.loadLibrary0(ClassLoader.java:2684) at java.base/java.lang.ClassLoader.loadLibrary(ClassLoader.java:2617) at java.base/java.lang.Runtime.load0(Runtime.java:767) at java.base/java.lang.System.load(System.java:1831) at org.apache.tomcat.jni.Library.<init>(Library.java:42) at org.apache.tomcat.jni.Library.initialize(Library.java:206) at org.apache.catalina.core.AprLifecycleListener.init(AprLifecycleListener.java:198) at org.apache.catalina.core.AprLifecycleListener.isAprAvailable(AprLifecycleListener.java:107) at org.apache.catalina.connector.Connector.<init>(Connector.java:83) at org.apache.catalina.startup.ConnectorCreateRule.begin(ConnectorCreateRule.java:67) at org.apache.tomcat.util.digester.Digester.startElement(Digester.java:1259) at java.xml/com.sun.org.apache.xerces.internal.parsers.AbstractSAXParser.startElement(AbstractSAXParser.java:510) at java.xml/com.sun.org.apache.xerces.internal.parsers.AbstractXMLDocumentParser.emptyElement(AbstractXMLDocumentParser.java:183) at java.xml/com.sun.org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl.scanStartElement(XMLDocumentFragmentScannerImpl.java:1377) at java.xml/com.sun.org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl$FragmentContentDriver.next(XMLDocumentFragmentScannerImpl.java:2708) at java.xml/com.sun.org.apache.xerces.internal.impl.XMLDocumentScannerImpl.next(XMLDocumentScannerImpl.java:605) at java.xml/com.sun.org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl.scanDocument(XMLDocumentFragmentScannerImpl.java:534) at java.xml/com.sun.org.apache.xerces.internal.parsers.XML11Configuration.parse(XML11Configuration.java:888) at java.xml/com.sun.org.apache.xerces.internal.parsers.XML11Configuration.parse(XML11Configuration.java:824) at java.xml/com.sun.org.apache.xerces.internal.parsers.XMLParser.parse(XMLParser.java:141) at java.xml/com.sun.org.apache.xerces.internal.parsers.AbstractSAXParser.parse(AbstractSAXParser.java:1216) at java.xml/com.sun.org.apache.xerces.internal.jaxp.SAXParserImpl$JAXPSAXParser.parse(SAXParserImpl.java:635) at org.apache.tomcat.util.digester.Digester.parse(Digester.java:1517) at org.apache.catalina.startup.Catalina.parseServerXml(Catalina.java:584) at org.apache.catalina.startup.Catalina.load(Catalina.java:675) at org.apache.catalina.startup.Catalina.load(Catalina.java:712) at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.base/java.lang.reflect.Method.invoke(Method.java:566) at org.apache.catalina.startup.Bootstrap.load(Bootstrap.java:302) at org.apache.catalina.startup.Bootstrap.main(Bootstrap.java:472) 26-Jun-2025 11:48:55.837 信息 [main] org.apache.catalina.startup.VersionLoggerListener.log Server.服务器版本: Apache Tomcat/9.0.37 26-Jun-2025 11:48:55.839 信息 [main] org.apache.catalina.startup.VersionLoggerListener.log 服务器构建: Jun 30 2020 20:09:49 UTC 26-Jun-2025 11:48:55.841 信息 [main] org.apache.catalina.startup.VersionLoggerListener.log 服务器版本号(: 9.0.37.0 26-Jun-2025 11:48:55.844 信息 [main] org.apache.catalina.startup.VersionLoggerListener.log 操作系统名称: Windows 7 26-Jun-2025 11:48:55.846 信息 [main] org.apache.catalina.startup.VersionLoggerListener.log OS.版本: 6.1 26-Jun-2025 11:48:55.847 信息 [main] org.apache.catalina.startup.VersionLoggerListener.log 架构: amd64 26-Jun-2025 11:48:55.850 信息 [main] org.apache.catalina.startup.VersionLoggerListener.log Java 环境变量: D:\jdk11_jb51 26-Jun-2025 11:48:55.852 信息 [main] org.apache.catalina.startup.VersionLoggerListener.log Java虚拟机版本: 11+28 26-Jun-2025 11:48:55.854 信息 [main] org.apache.catalina.startup.VersionLoggerListener.log JVM.供应商: Oracle Corporation 26-Jun-2025 11:48:55.856 信息 [main] org.apache.catalina.startup.VersionLoggerListener.log CATALINA_BASE: D:\apache-tomcat-9.0.37 26-Jun-2025 11:48:55.858 信息 [main] org.apache.catalina.startup.VersionLoggerListener.log CATALINA_HOME: D:\apache-tomcat-9.0.37 26-Jun-2025 11:48:55.861 信息 [main] org.apache.catalina.startup.VersionLoggerListener.log 命令行参数:--add-opens=java.base/java.lang=ALL-UNNAMED 26-Jun-2025 11:48:55.864 信息 [main] org.apache.catalina.startup.VersionLoggerListener.log 命令行参数:--add-opens=java.base/java.io=ALL-UNNAMED 26-Jun-2025 11:48:55.867 信息 [main] org.apache.catalina.startup.VersionLoggerListener.log 命令行参数:--add-opens=java.rmi/sun.rmi.transport=ALL-UNNAMED 26-Jun-2025 11:48:55.870 信息 [main] org.apache.catalina.startup.VersionLoggerListener.log 命令行参数:-Djava.util.logging.config.file=D:\apache-tomcat-9.0.37\conf\logging.properties 26-Jun-2025 11:48:55.872 信息 [main] org.apache.catalina.startup.VersionLoggerListener.log 命令行参数:-Djava.util.logging.manager=org.apache.juli.ClassLoaderLogManager 26-Jun-2025 11:48:55.874 信息 [main] org.apache.catalina.startup.VersionLoggerListener.log 命令行参数:-Djdk.tls.ephemeralDHKeySize=2048 26-Jun-2025 11:48:55.876 信息 [main] org.apache.catalina.startup.VersionLoggerListener.log 命令行参数:-Djava.protocol.handler.pkgs=org.apache.catalina.webresources 26-Jun-2025 11:48:55.879 信息 [main] org.apache.catalina.startup.VersionLoggerListener.log 命令行参数:-Dignore.endorsed.dirs= 26-Jun-2025 11:48:55.881 信息 [main] org.apache.catalina.startup.VersionLoggerListener.log 命令行参数:-Dcatalina.base=D:\apache-tomcat-9.0.37 26-Jun-2025 11:48:55.883 信息 [main] org.apache.catalina.startup.VersionLoggerListener.log 命令行参数:-Dcatalina.home=D:\apache-tomcat-9.0.37 26-Jun-2025 11:48:55.885 信息 [main] org.apache.catalina.startup.VersionLoggerListener.log 命令行参数:-Djava.io.tmpdir=D:\apache-tomcat-9.0.37\temp 26-Jun-2025 11:48:56.667 信息 [main] org.apache.coyote.AbstractProtocol.init 初始化协议处理器 ["http-nio-8080"] 26-Jun-2025 11:48:56.844 信息 [main] org.apache.catalina.startup.Catalina.load 服务器在[1446]毫秒内初始化 26-Jun-2025 11:48:56.971 信息 [main] org.apache.catalina.core.StandardService.startInternal 正在启动服务[Catalina] 26-Jun-2025 11:48:56.973 信息 [main] org.apache.catalina.core.StandardEngine.startInternal 正在启动 Servlet 引擎:[Apache Tomcat/9.0.37] 26-Jun-2025 11:48:57.006 信息 [main] org.apache.catalina.startup.HostConfig.deployWAR 正在部署web应用程序存档文件[D:\apache-tomcat-9.0.37\webapps\KuCun2.war] 26-Jun-2025 11:49:01.871 信息 [main] org.apache.jasper.servlet.TldScanner.scanJars 至少有一个JAR被扫描用于TLD但尚未包含TLD。 为此记录器启用调试日志记录,以获取已扫描但未在其中找到TLD的完整JAR列表。 在扫描期间跳过不需要的JAR可以缩短启动时间和JSP编译时间。 26-Jun-2025 11:49:18.187 信息 [main] org.apache.catalina.startup.HostConfig.deployWAR web应用程序存档文件[D:\apache-tomcat-9.0.37\webapps\KuCun2.war]的部署已在[21,180]ms内完成 26-Jun-2025 11:49:18.190 信息 [main] org.apache.catalina.startup.HostConfig.deployDirectory 把web 应用程序部署到目录 [D:\apache-tomcat-9.0.37\webapps\docs] 26-Jun-2025 11:49:18.245 信息 [main] org.apache.catalina.startup.HostConfig.deployDirectory Web应用程序目录[D:\apache-tomcat-9.0.37\webapps\docs]的部署已在[56]毫秒内完成 26-Jun-2025 11:49:18.247 信息 [main] org.apache.catalina.startup.HostConfig.deployDirectory 把web 应用程序部署到目录 [D:\apache-tomcat-9.0.37\webapps\examples] 26-Jun-2025 11:49:18.654 信息 [main] org.apache.catalina.startup.HostConfig.deployDirectory Web应用程序目录[D:\apache-tomcat-9.0.37\webapps\examples]的部署已在[407]毫秒内完成 26-Jun-2025 11:49:18.658 信息 [main] org.apache.catalina.startup.HostConfig.deployDirectory 把web 应用程序部署到目录 [D:\apache-tomcat-9.0.37\webapps\host-manager] 26-Jun-2025 11:49:18.703 信息 [main] org.apache.catalina.startup.HostConfig.deployDirectory Web应用程序目录[D:\apache-tomcat-9.0.37\webapps\host-manager]的部署已在[45]毫秒内完成 26-Jun-2025 11:49:18.709 信息 [main] org.apache.catalina.startup.HostConfig.deployDirectory 把web 应用程序部署到目录 [D:\apache-tomcat-9.0.37\webapps\manager] 26-Jun-2025 11:49:18.758 信息 [main] org.apache.catalina.startup.HostConfig.deployDirectory Web应用程序目录[D:\apache-tomcat-9.0.37\webapps\manager]的部署已在[50]毫秒内完成 26-Jun-2025 11:49:18.764 信息 [main] org.apache.catalina.startup.HostConfig.deployDirectory 把web 应用程序部署到目录 [D:\apache-tomcat-9.0.37\webapps\ROOT] 26-Jun-2025 11:49:18.810 信息 [main] org.apache.catalina.startup.HostConfig.deployDirectory Web应用程序目录[D:\apache-tomcat-9.0.37\webapps\ROOT]的部署已在[47]毫秒内完成 26-Jun-2025 11:49:18.820 信息 [main] org.apache.coyote.AbstractProtocol.start 开始协议处理句柄["http-nio-8080"] 26-Jun-2025 11:49:18.845 信息 [main] org.apache.catalina.startup.Catalina.start [22000]毫秒后服务器启动 26-Jun-2025 11:49:56.871 信息 [Thread-4] org.apache.coyote.AbstractProtocol.pause 暂停ProtocolHandler["http-nio-8080"] 26-Jun-2025 11:49:56.912 信息 [Thread-4] org.apache.catalina.core.StandardService.stopInternal 正在停止服务[Catalina] 26-Jun-2025 11:49:57.187 警告 [Thread-4] org.apache.catalina.loader.WebappClassLoaderBase.clearReferencesThreads Web应用程序[KuCun2]似乎启动了一个名为[mysql-cj-abandoned-connection-cleanup]的线程,但未能停止它。这很可能会造成内存泄漏。线程的堆栈跟踪:[ java.base@11/java.lang.Object.wait(Native Method) java.base@11/java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:155) com.mysql.cj.jdbc.AbandonedConnectionCleanupThread.run(AbandonedConnectionCleanupThread.java:91) java.base@11/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128) java.base@11/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628) java.base@11/java.lang.Thread.run(Thread.java:834)] 26-Jun-2025 11:49:57.214 信息 [Thread-4] org.apache.coyote.AbstractProtocol.stop 正在停止ProtocolHandler ["http-nio-8080"] 26-Jun-2025 11:49:57.223 信息 [Thread-4] org.apache.coyote.AbstractProtocol.destroy 正在摧毁协议处理器 ["http-nio-8080"] ------------------------ host-manager.2025-06-26.log ------------------------ ------------------------ localhost.2025-06-26.log ------------------------ 26-Jun-2025 11:48:04.218 信息 [Thread-4] org.apache.catalina.core.ApplicationContext.log SessionListener: contextDestroyed() 26-Jun-2025 11:48:04.218 信息 [Thread-4] org.apache.catalina.core.ApplicationContext.log ContextListener: contextDestroyed() 26-Jun-2025 11:49:02.103 信息 [main] org.apache.catalina.core.ApplicationContext.log 2 Spring WebApplicationInitializers detected on classpath 26-Jun-2025 11:49:07.916 信息 [main] org.apache.catalina.core.ApplicationContext.log Initializing Spring embedded WebApplicationContext 26-Jun-2025 11:49:18.643 信息 [main] org.apache.catalina.core.ApplicationContext.log ContextListener: contextInitialized() 26-Jun-2025 11:49:18.644 信息 [main] org.apache.catalina.core.ApplicationContext.log SessionListener: contextInitialized() 26-Jun-2025 11:49:18.646 信息 [main] org.apache.catalina.core.ApplicationContext.log ContextListener: attributeAdded('StockTicker', 'async.Stockticker@13bf8a36') 26-Jun-2025 11:49:56.945 信息 [Thread-4] org.apache.catalina.core.ApplicationContext.log SessionListener: contextDestroyed() 26-Jun-2025 11:49:56.945 信息 [Thread-4] org.apache.catalina.core.ApplicationContext.log ContextListener: contextDestroyed() 26-Jun-2025 11:49:56.970 信息 [Thread-4] org.apache.catalina.core.ApplicationContext.log Closing Spring root WebApplicationContext ------------------------ localhost_access_log.2025-06-26.txt ------------------------ ------------------------ manager.2025-06-26.log ------------------------
06-27
<think>根据提供的Tomcat日志,我们主要需要解决两个问题:1.内存泄漏警告:Web应用程序[KuCun2]在停止时未能停止名为[mysql-cj-abandoned-connection-cleanup]的线程,可能导致内存泄漏。2.32位与64位不兼容的警告:加载tcnative-1.dll时出错(Can'tloadIA32-bit.dllonaAMD64-bitplatform)。解决方案如下:问题1:内存泄漏(MySQLJDBC驱动程序线程未停止)原因:MySQLJDBC驱动程序在Web应用程序启动时会启动一个名为"mysql-cj-abandoned-connection-cleanup"的守护线程,用于清理被遗弃的连接。当Web应用程序停止时,Tomcat尝试停止所有由Web应用程序类加载器加载的线程,但这个线程是由驱动程序启动的,且没有被正确停止。解决方案:方法1:在Web应用程序的上下文销毁时,手动停止该线程(推荐)。方法2:升级MySQLJDBC驱动版本(可能已经修复)。方法3:在Tomcat的context.xml中配置<Context>元素,设置JAR扫描规则,避免扫描到驱动程序的JAR,从而让驱动程序由Tomcat的类加载器加载(这样在停止Web应用时不会强制注销驱动)。这里我们使用方法1,在Web应用程序中添加一个ServletContextListener,在contextDestroyed方法中停止该线程。代码示例:创建一个自定义的ServletContextListener:```javapackagecom.example.listener;importjava.lang.reflect.Field;importjava.util.Set;importjava.util.concurrent.ThreadPoolExecutor;importjava.util.concurrent.TimeUnit;importjavax.servlet.ServletContextEvent;importjavax.servlet.ServletContextListener;importjavax.servlet.annotation.WebListener;@WebListenerpublicclassMysqlThreadCleanupListenerimplementsServletContextListener{@OverridepublicvoidcontextInitialized(ServletContextEventsce){//初始化时不需要做任何事}@OverridepublicvoidcontextDestroyed(ServletContextEventsce){shutdownMysqlAbandonedConnectionCleanupThread();}privatevoidshutdownMysqlAbandonedConnectionCleanupThread(){try{//尝试通过反射获取MySQL的清理线程Class<?>cls=Class.forName("com.mysql.cj.jdbc.AbandonedConnectionCleanupThread");//获取静态字段'threadRef'(在较新的驱动中可能是'thread')FieldthreadField=cls.getDeclaredField("thread");threadField.setAccessible(true);Threadthread=(Thread)threadField.get(null);if(thread!=null){thread.interrupt();thread.join(1000);if(thread.isAlive()){//如果线程还在运行,尝试使用ExecutorService的方式关闭Fieldfield=cls.getDeclaredField("executorService");field.setAccessible(true);ThreadPoolExecutorexecutor=(ThreadPoolExecutor)field.get(null);if(executor!=null){executor.shutdown();if(!executor.awaitTermination(1,TimeUnit.SECONDS)){executor.shutdownNow();}}}}//重置线程为nullthreadField.set(null,null);}catch(ClassNotFoundExceptione){//忽略,可能没有使用MySQL驱动}catch(Exceptione){System.err.println("ErrorshuttingdownMySQLAbandonedConnectionCleanupThread:"+e.getMessage());}}}```问题2:32位与64位不兼容原因:Tomcat尝试加载一个32位的本地库(tcnative-1.dll),但运行在64位的JVM上。解决方案:方法1:删除或替换为64位的tcnative-1.dll。方法2:如果不需要APR连接器,可以忽略此警告(不影响Tomcat运行)。步骤:1.确认操作系统是64位,且安装了64位的JDK。2.下载与Tomcat版本对应的64位tcnative-1.dll(可以从ApacheTomcat官网下载,或者从Tomcat的bin目录中删除现有的32位dll文件,然后放入64位dll)。3.或者,直接删除bin目录下的tcnative-1.dll(因为Tomcat默认使用NIO连接器,不需要APR)。操作:删除D:\apache-tomcat-9.0.37\bin\tcnative-1.dll另外,还可以通过配置来禁用APR监听器,在conf/server.xml中注释掉APR相关的连接器(但默认配置中并没有启用APR连接器,所以警告只是来自监听器初始化)。在conf/server.xml中,默认的连接器是NIO,不是APR,所以这个警告可以忽略。但如果想消除警告,可以删除或替换dll文件。综合以上,我们给出两个问题的解决方案。注意:对于内存泄漏问题,我们提供的监听器代码需要添加到Web应用程序(KuCun2)中,并重新打包WAR文件。如果无法修改应用程序,还可以尝试在Tomcat的context.xml中配置:```xml<Context>...<JarScanner><JarScanFilterdefaultPluggabilityScan="false"tldScan="false"/></JarScanner></Context>```但这种方法可能会影响其他功能,不推荐。因此,推荐修改应用程序,添加监听器。下面提供完整的解决方案步骤:步骤1:修改Web应用程序(KuCun2),添加一个ServletContextListener来停止MySQL的清理线程。步骤2:重新打包WAR文件并部署。步骤3:删除Tomcat的bin目录下32位的tcnative-1.dll(或者替换为64位版本)。对于步骤2,如果不想修改应用程序,可以尝试升级MySQLJDBC驱动到最新版本(可能已经修复了线程关闭的问题)。升级驱动:将mysql-connector-java升级到至少8.0.22版本(该版本修复了内存泄漏问题)。因此,另一种方案:方案A:升级驱动(推荐,简单且官方修复)。方案B:添加自定义监听器(如果升级驱动后问题仍存在,再使用)。所以,优先尝试升级MySQL驱动。在pom.xml中更新依赖:```xml<dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>8.0.27</version><!--使用最新稳定版本--></dependency>```然后重新打包应用。总结:1.升级MySQL驱动到最新版本(8.0.22+)以解决内存泄漏。2.删除或替换Tomcat的bin目录下的tcnative-1.dll文件(32位)为64位版本,或直接删除(因为不需要)。如果升级驱动后仍然出现线程未停止的警告,再考虑添加自定义监听器。最后,提供相关问题的提问。</think>### 解决 Tomcat 日志中的关键问题分析 根据您提供的 Tomcat 日志,我发现了两个主要问题需要解决:内存泄漏警告和 32/64 位兼容性问题。以下是完整的解决方案: #### 问题1:MySQL JDBC 驱动内存泄漏(关键问题) **日志警告:** ``` 26-Jun-2025 11:49:57.187 警告 [Thread-4] org.apache.catalina.loader.WebappClassLoaderBase.clearReferencesThreads Web应用程序[KuCun2]似乎启动了一个名为[mysql-cj-abandoned-connection-cleanup]的线程,但未能停止它。 这很可能会造成内存泄漏。 ``` **解决方案:** 1. **在 web.xml 中添加监听器强制关闭线程**: ```xml <!-- 在 KuCun2 应用的 web.xml 中添加 --> <listener> <listener-class>com.mysql.cj.jdbc.AbandonedConnectionCleanupThread</listener-class> </listener> ``` 2. **应用关闭时手动停止线程的 Java 代码**: ```java package com.yourpackage.util; import com.mysql.cj.jdbc.AbandonedConnectionCleanupThread; import javax.servlet.ServletContextEvent; import javax.servlet.ServletContextListener; import java.sql.Driver; import java.sql.DriverManager; import java.sql.SQLException; import java.util.Enumeration; public class MysqlCleanupListener implements ServletContextListener { @Override public void contextInitialized(ServletContextEvent sce) { // 初始化时不执行任何操作 } @Override public void contextDestroyed(ServletContextEvent sce) { // 1. 停止MySQL的废弃连接清理线程 AbandonedConnectionCleanupThread.checkedShutdown(); // 2. 注销JDBC驱动 Enumeration<Driver> drivers = DriverManager.getDrivers(); while (drivers.hasMoreElements()) { Driver driver = drivers.nextElement(); try { DriverManager.deregisterDriver(driver); System.out.println("注销JDBC驱动: " + driver.getClass().getName()); } catch (SQLException e) { System.err.println("注销JDBC驱动失败: " + e.getMessage()); } } // 3. 清除线程本地变量 ThreadLocal<?> threadLocal = null; try { Class<?> clazz = Class.forName("com.mysql.cj.jdbc.ConnectionImpl"); Field threadLocalField = clazz.getDeclaredField("threadLocalConnectionClosed"); threadLocalField.setAccessible(true); threadLocal = (ThreadLocal<?>) threadLocalField.get(null); } catch (Exception e) { // 忽略反射异常 } if (threadLocal != null) { threadLocal.remove(); } } } ``` 3. **在 web.xml 中注册此监听器**: ```xml <listener> <listener-class>com.yourpackage.util.MysqlCleanupListener</listener-class> </listener> ``` #### 问题2:32/64 位不兼容问题 **日志错误:** ``` 26-Jun-2025 11:48:55.666 警告 [main] org.apache.catalina.core.AprLifecycleListener.init 基于APR的本地库加载失败.错误报告为[D:\apache-tomcat-9.0.37\bin\tcnative-1.dll: Can't load IA 32-bit .dll on a AMD 64-bit platform] ``` **解决方案:** 1. **删除或替换不兼容的 DLL 文件**: ```batch :: 删除32位dll文件 del /f D:\apache-tomcat-9.0.37\bin\tcnative-1.dll :: 下载64位版本 (Tomcat 9.0.37) curl -L -o D:\apache-tomcat-9.0.37\bin\tcnative-1.dll ^ https://archive.apache.org/dist/tomcat/tomcat-connectors/native/1.2.26/binaries/tomcat-native-1.2.26-win64-bin.zip ``` 2. **禁用 APR 连接器(如果不使用)**: ```xml <!-- 修改 conf/server.xml --> <Listener className="org.apache.catalina.core.AprLifecycleListener" SSLEngine="off" /> ``` 3. **验证 JVM 架构一致性**: ```batch @echo off set JAVA_HOME=D:\jdk11_jb51 set CATALINA_HOME=D:\apache-tomcat-9.0.37 %JAVA_HOME%\bin\java -version echo 检查架构一致性... wmic os get osarchitecture ``` #### 问题3:JAR 扫描警告 **日志信息:** ``` 26-Jun-2025 11:49:01.871 信息 [main] org.apache.jasper.servlet.TldScanner.scanJars 至少有一个JAR被扫描用于TLD但尚未包含TLD。 ``` **解决方案:** ```xml <!-- 在 context.xml 中添加 JAR 扫描过滤 --> <Context> <JarScanner> <JarScanFilter tldScan="*.jar" tldSkip="bootstrap.jar,tomcat-juli.jar,annotations-api.jar,ecj-*.jar"/> </JarScanner> </Context> ``` ### 自动诊断和修复脚本 创建 `tomcat_fix.bat` 脚本自动处理问题: ```batch @echo off setlocal set CATALINA_HOME=D:\apache-tomcat-9.0.37 set JAVA_HOME=D:\jdk11_jb51 echo 解决MySQL内存泄漏问题... echo 创建 MysqlCleanupListener.java... ( echo package com.yourpackage.util; echo echo import com.mysql.cj.jdbc.AbandonedConnectionCleanupThread; echo import javax.servlet.ServletContextEvent; echo import javax.servlet.ServletContextListener; echo import java.sql.Driver; echo import java.sql.DriverManager; echo import java.sql.SQLException; echo import java.util.Enumeration; echo import java.lang.reflect.Field; echo echo public class MysqlCleanupListener implements ServletContextListener { echo echo @Override echo public void contextInitialized(ServletContextEvent sce) {} echo echo @Override echo public void contextDestroyed(ServletContextEvent sce) { echo AbandonedConnectionCleanupThread.checkedShutdown(); echo Enumeration<Driver> drivers = DriverManager.getDrivers(); echo while (drivers.hasMoreElements()) { echo Driver driver = drivers.nextElement(); echo try { echo DriverManager.deregisterDriver(driver); echo } catch (SQLException e) { } echo } echo try { echo Class<?> clazz = Class.forName("com.mysql.cj.jdbc.ConnectionImpl"); echo Field threadLocalField = clazz.getDeclaredField("threadLocalConnectionClosed"); echo threadLocalField.setAccessible(true); echo ThreadLocal<?> threadLocal = (ThreadLocal<?>) threadLocalField.get(null); echo if (threadLocal != null) threadLocal.remove(); echo } catch (Exception e) { } echo } echo } )> "%CATALINA_HOME%\webapps\KuCun2\WEB-INF\src\com\yourpackage\util\MysqlCleanupListener.java" echo 更新web.xml... ( echo ^<listener^> echo ^<listener-class^>com.yourpackage.util.MysqlCleanupListener^</listener-class^> echo ^</listener^> ) >> "%CATALINA_HOME%\webapps\KuCun2\WEB-INF\web.xml" echo 解决32/64位兼容问题... del /f /q "%CATALINA_HOME%\bin\tcnative-1.dll" echo 已删除32位tcnative-1.dll echo 禁用APR监听器(可选)... findstr /v "AprLifecycleListener" "%CATALINA_HOME%\conf\server.xml" > temp.xml move /y temp.xml "%CATALINA_HOME%\conf\server.xml" echo 优化TLD扫描配置... ( echo ^<Context^> echo ^<JarScanner^> echo ^<JarScanFilter echo tldScan="*.jar" echo tldSkip="bootstrap.jar,tomcat-juli.jar,annotations-api.jar,ecj-*.jar"/^> echo ^</JarScanner^> echo ^</Context^> ) > "%CATALINA_HOME%\conf\context.xml" echo 清理临时文件... del /f /q "%CATALINA_HOME%\work\*.*" del /f /q "%CATALINA_HOME%\temp\*.*" echo 重启Tomcat服务... net stop Tomcat9 net start Tomcat9 endlocal echo 修复完成! ``` ### 验证修复效果 1. **检查内存泄漏是否解决**: - 停止 KuCun2 应用时,日志中不再出现 `mysql-cj-abandoned-connection-cleanup` 警告 2. **验证 64 位兼容性**: - 启动日志中不再出现 `Can't load IA 32-bit .dll` 错误 3. **检查 TLD 扫描警告**: - 启动日志中不再出现 `至少有一个JAR被扫描用于TLD但尚未包含TLD` 信息 ### 最佳实践建议 1. **定期维护**: ```bat rem 每月执行清理 del /q /f "%CATALINA_HOME%\logs\*.log" del /q /f "%CATALINA_HOME%\work\*.*" ``` 2. **内存优化**: ```bat rem 在 catalina.bat 中添加 set JAVA_OPTS=-Xms512m -Xmx2048m -XX:MaxMetaspaceSize=512m ``` 3. **连接池配置**: ```xml <!-- 在 context.xml 中配置 --> <Resource name="jdbc/YourDB" auth="Container" type="javax.sql.DataSource" maxTotal="100" maxIdle="30" maxWaitMillis="10000" validationQuery="SELECT 1"/> ``` --- ###
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值