Java Melody 在 xampp tomcat8 上不显示任何 sql 数据
在 Windows 11 上的 Xampp Tomcat 上,我尝试使用 java melody 监视 java-web-app。
但是java melody检测不到sql数据。
你能弄清楚我错过了什么吗?
我创建了一个库项目,而不是在每个应用程序上进行相同的设置
这是项目代码...
pom.xml:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.tugalsan</groupId>
<artifactId>api-profile</artifactId>
<version>1.0-SNAPSHOT</version>
<dependencies>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>4.0.1</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>net.bull.javamelody</groupId>
<artifactId>javamelody-core</artifactId>
<version>1.90.0</version>
</dependency>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>api-url</artifactId>
<version>${project.version}</version>
</dependency>
</dependencies>
<build>
<resources>
<resource>
<directory>src/main/java</directory>
<includes>
<include>**/*.java</include>
<include>**/*.gwt.xml</include>
</includes>
</resource>
<resource>
<directory>src/main/resources</directory>
<includes>
<include>**/*.*</include>
</includes>
</resource>
</resources>
<pluginManagement>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-source-plugin</artifactId>
<version>3.2.1</version>
<executions>
<execution>
<id>attach-sources</id>
<phase>package</phase>
<goals>
<goal>jar-no-fork</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</pluginManagement>
</build>
<properties>
<maven.compiler.source>15</maven.compiler.source>
<maven.compiler.target>15</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
</project>
TGS_ProfileServletUtils.java:
package com.tugalsan.api.profile.client;
import com.tugalsan.api.url.client.parser.*;
public class TGS_ProfileServletUtils {
final public static String SERVLET_NAME = "monitoring";//HARD-CODED IN LIB, THIS CANNOT BE CHANGED!
}
TS_ProfileMelodyUtils.java:
package com.tugalsan.api.profile.server.melody;
import java.sql.*;
import javax.sql.*;
import javax.servlet.*;
import javax.servlet.annotation.*;
import net.bull.javamelody.*;
import com.tugalsan.api.profile.client.*;
public class TS_ProfileMelodyUtils {
@WebFilter(
filterName = TGS_ProfileServletUtils.SERVLET_NAME,
dispatcherTypes = {DispatcherType.REQUEST, DispatcherType.ASYNC},
asyncSupported = true,
urlPatterns = {"/*"},
initParams = {
@WebInitParam(name = "async-supported", value = "true")
}
)
final public static class MelodyFilter extends MonitoringFilter {
}
@WebListener
final public static class MelodyListener extends SessionListener {
}
public static Connection createProxy(Connection con) {
try {
DriverManager.registerDriver(new net.bull.javamelody.JdbcDriver());
return JdbcWrapper.SINGLETON.createConnectionProxy(con);
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
public static DataSource createProxy(DataSource ds) {
try {
DriverManager.registerDriver(new net.bull.javamelody.JdbcDriver());
return JdbcWrapper.SINGLETON.createDataSourceProxy(ds);
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
}
辅助类
package com.tugalsan.api.sql.conn.server;
import java.io.Serializable;
import java.util.Objects;
public class TS_SQLConnConfig implements Serializable {
public int method = TS_SQLConnMethodUtils.METHOD_MYSQL();
public String dbName;
public String dbIp = "localhost";
public int dbPort = 3306;
public String dbUser = "root";
public String dbPassword = "";
public boolean autoReconnect = true;
public boolean useSSL = false;
public boolean region_ist = true;
public boolean charsetUTF8 = true;
public boolean isPooled = true;
public TS_SQLConnConfig() {//DTO
}
public TS_SQLConnConfig(CharSequence dbName) {
this.dbName = dbName == null ? null : dbName.toString();
}
}
在另一个 API 上,这就是我创建池的方式
(我跳过了一些与问题无关的类文件)
public static PoolProperties create(TS_SQLConnConfig config) {
var pool = new PoolProperties();
pool.setUrl(TS_SQLConnURLUtils.create(config));
pool.setDriverClassName(TS_SQLConnMethodUtils.getDriver(config));
if (TGS_StringUtils.isPresent(config.dbUser) && TGS_StringUtils.isPresent(config.dbPassword)) {
pool.setUsername(config.dbUser);
pool.setPassword(config.dbPassword);
}
var maxActive = 200;
pool.setMaxActive(maxActive);
pool.setInitialSize(maxActive / 10);
pool.setJmxEnabled(true);
pool.setTestWhileIdle(true);
pool.setTestOnBorrow(true);
pool.setTestOnReturn(false);
pool.setValidationQuery("SELECT 1");
pool.setValidationInterval(30000);
pool.setTimeBetweenEvictionRunsMillis(30000);
pool.setMaxWait(10000);
pool.setMinEvictableIdleTimeMillis(30000);
pool.setMinIdle(10);
pool.setFairQueue(true);
pool.setLogAbandoned(true);
pool.setRemoveAbandonedTimeout(600);
pool.setRemoveAbandoned(true);
pool.setJdbcInterceptors(
"org.apache.tomcat.jdbc.pool.interceptor.ConnectionState;"
+ "org.apache.tomcat.jdbc.pool.interceptor.StatementFinalizer;"
+ "org.apache.tomcat.jdbc.pool.interceptor.ResetAbandonedTimer");
return pool;
}
WAY1:
//I created datasource once, save it as a global variable inside a ConcurrentLinkedQueue.
var pool_ds = new DataSource(create(config));
//then for every connection need, i created an extra proxy like this.
var pool_con = pool_ds.getConnection();
var proxy_con = TS_ProfileMelodyUtils.createProxy(pool_con);
//and close both of them later on
方式2:
//I created datasource once, save it as a global variable inside a ConcurrentLinkedQueue.
var pool_ds = new DataSource(create(config));
//then i created a proxy datasource, save it as a global variable too
var dsProxy = TS_ProfileMelodyUtils.createProxy(ds);
//then for every connection need, i did not create a proxy connection.
var pool_con = pool_ds.getConnection();
//and close connection later on
方式 3:
//I created datasource once, save it as a global variable inside a ConcurrentLinkedQueue.
var pool_ds = new DataSource(create(config));
//then i created a proxy datasource, save it as a global variable too
var dsProxy = TS_ProfileMelodyUtils.createProxy(ds);
//then for every connection need, i created an extra proxy like this.
var pool_con = pool_ds.getConnection();
var proxy_con = TS_ProfileMelodyUtils.createProxy(pool_con);
//and close both of them later on
On Xampp Tomcat on Windows 11, I am trying to monitor java-web-app with java melody.
However, sql data is not detected by java melody.
Could you figure out what i am missing?
I have created a library project, not to do same settings on every app
Here is the projects code...
pom.xml:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.tugalsan</groupId>
<artifactId>api-profile</artifactId>
<version>1.0-SNAPSHOT</version>
<dependencies>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>4.0.1</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>net.bull.javamelody</groupId>
<artifactId>javamelody-core</artifactId>
<version>1.90.0</version>
</dependency>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>api-url</artifactId>
<version>${project.version}</version>
</dependency>
</dependencies>
<build>
<resources>
<resource>
<directory>src/main/java</directory>
<includes>
<include>**/*.java</include>
<include>**/*.gwt.xml</include>
</includes>
</resource>
<resource>
<directory>src/main/resources</directory>
<includes>
<include>**/*.*</include>
</includes>
</resource>
</resources>
<pluginManagement>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-source-plugin</artifactId>
<version>3.2.1</version>
<executions>
<execution>
<id>attach-sources</id>
<phase>package</phase>
<goals>
<goal>jar-no-fork</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</pluginManagement>
</build>
<properties>
<maven.compiler.source>15</maven.compiler.source>
<maven.compiler.target>15</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
</project>
TGS_ProfileServletUtils.java:
package com.tugalsan.api.profile.client;
import com.tugalsan.api.url.client.parser.*;
public class TGS_ProfileServletUtils {
final public static String SERVLET_NAME = "monitoring";//HARD-CODED IN LIB, THIS CANNOT BE CHANGED!
}
TS_ProfileMelodyUtils.java:
package com.tugalsan.api.profile.server.melody;
import java.sql.*;
import javax.sql.*;
import javax.servlet.*;
import javax.servlet.annotation.*;
import net.bull.javamelody.*;
import com.tugalsan.api.profile.client.*;
public class TS_ProfileMelodyUtils {
@WebFilter(
filterName = TGS_ProfileServletUtils.SERVLET_NAME,
dispatcherTypes = {DispatcherType.REQUEST, DispatcherType.ASYNC},
asyncSupported = true,
urlPatterns = {"/*"},
initParams = {
@WebInitParam(name = "async-supported", value = "true")
}
)
final public static class MelodyFilter extends MonitoringFilter {
}
@WebListener
final public static class MelodyListener extends SessionListener {
}
public static Connection createProxy(Connection con) {
try {
DriverManager.registerDriver(new net.bull.javamelody.JdbcDriver());
return JdbcWrapper.SINGLETON.createConnectionProxy(con);
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
public static DataSource createProxy(DataSource ds) {
try {
DriverManager.registerDriver(new net.bull.javamelody.JdbcDriver());
return JdbcWrapper.SINGLETON.createDataSourceProxy(ds);
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
}
a helper class
package com.tugalsan.api.sql.conn.server;
import java.io.Serializable;
import java.util.Objects;
public class TS_SQLConnConfig implements Serializable {
public int method = TS_SQLConnMethodUtils.METHOD_MYSQL();
public String dbName;
public String dbIp = "localhost";
public int dbPort = 3306;
public String dbUser = "root";
public String dbPassword = "";
public boolean autoReconnect = true;
public boolean useSSL = false;
public boolean region_ist = true;
public boolean charsetUTF8 = true;
public boolean isPooled = true;
public TS_SQLConnConfig() {//DTO
}
public TS_SQLConnConfig(CharSequence dbName) {
this.dbName = dbName == null ? null : dbName.toString();
}
}
On another api, this is how i create a pool
(I skipped some class files, unrelated to the question)
public static PoolProperties create(TS_SQLConnConfig config) {
var pool = new PoolProperties();
pool.setUrl(TS_SQLConnURLUtils.create(config));
pool.setDriverClassName(TS_SQLConnMethodUtils.getDriver(config));
if (TGS_StringUtils.isPresent(config.dbUser) && TGS_StringUtils.isPresent(config.dbPassword)) {
pool.setUsername(config.dbUser);
pool.setPassword(config.dbPassword);
}
var maxActive = 200;
pool.setMaxActive(maxActive);
pool.setInitialSize(maxActive / 10);
pool.setJmxEnabled(true);
pool.setTestWhileIdle(true);
pool.setTestOnBorrow(true);
pool.setTestOnReturn(false);
pool.setValidationQuery("SELECT 1");
pool.setValidationInterval(30000);
pool.setTimeBetweenEvictionRunsMillis(30000);
pool.setMaxWait(10000);
pool.setMinEvictableIdleTimeMillis(30000);
pool.setMinIdle(10);
pool.setFairQueue(true);
pool.setLogAbandoned(true);
pool.setRemoveAbandonedTimeout(600);
pool.setRemoveAbandoned(true);
pool.setJdbcInterceptors(
"org.apache.tomcat.jdbc.pool.interceptor.ConnectionState;"
+ "org.apache.tomcat.jdbc.pool.interceptor.StatementFinalizer;"
+ "org.apache.tomcat.jdbc.pool.interceptor.ResetAbandonedTimer");
return pool;
}
WAY1:
//I created datasource once, save it as a global variable inside a ConcurrentLinkedQueue.
var pool_ds = new DataSource(create(config));
//then for every connection need, i created an extra proxy like this.
var pool_con = pool_ds.getConnection();
var proxy_con = TS_ProfileMelodyUtils.createProxy(pool_con);
//and close both of them later on
WAY2:
//I created datasource once, save it as a global variable inside a ConcurrentLinkedQueue.
var pool_ds = new DataSource(create(config));
//then i created a proxy datasource, save it as a global variable too
var dsProxy = TS_ProfileMelodyUtils.createProxy(ds);
//then for every connection need, i did not create a proxy connection.
var pool_con = pool_ds.getConnection();
//and close connection later on
WAY2 RESULT: (same, nothing changed)
WAY3:
//I created datasource once, save it as a global variable inside a ConcurrentLinkedQueue.
var pool_ds = new DataSource(create(config));
//then i created a proxy datasource, save it as a global variable too
var dsProxy = TS_ProfileMelodyUtils.createProxy(ds);
//then for every connection need, i created an extra proxy like this.
var pool_con = pool_ds.getConnection();
var proxy_con = TS_ProfileMelodyUtils.createProxy(pool_con);
//and close both of them later on
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
我想我发现了问题。
应该从 proxy_datasource 而不是 pool_datasource 创建连接
var pool_con = pool_ds.getConnection(); //错误
var pool_con = proxy_ds.getConnection(); //右
而且,在创建语句时,
应该使用代理连接(proxy_con)来创建语句,而不是主连接(pool_con)!
我用的是方式3,结果是单例。我认为 java melody 检测到它已经有一个数据源;并且不会记录两次。
完整代码:位于 github-profile
完整代码:位于 github-sql-conn
I think i found the problem.
One should create connection from proxy_datasource not pool_datasource
var pool_con = pool_ds.getConnection(); //WRONG
var pool_con = proxy_ds.getConnection(); //RIGHT
And also, on creating statements,
one should use proxy connections (proxy_con) to create statements, not main connection (pool_con)!
I used way 3. And the results were singleton. I think java melody detects that it has a datasource already; and does not log twice.
full code: at github-profile
full code: at github-sql-conn