MX4J是一个开源JMX管理框架,支持JSR3 (JMX) 和JSR160 (JMX Remote API)。通过spring将MX4J集成到我们的应用系统中,可以通过HTTP协议适配,能够基于Web的方式来实现对应用系统的监控和管理。这里,使用的版本分别为:
- Spring 2.5
-
MX4J 3.0.2
MX4J对应的几个JAR文件,加入到CLASSPATH:
- mx4j.jar
- mx4j-impl.jar
- mx4j-jmx.jar
- mx4j-remote.jar
- mx4j-rimpl.jar
- mx4j-rjmx.jar
- mx4j-tools.jar
首先,给出Spring的完整配置,如下所示:
- <?xml version="1.0" encoding="UTF-8"?>
- <beans xmlns="http://www.springframework.org/schema/beans"
- xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"
- xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">
- <bean id="exporter" class="org.springframework.jmx.export.MBeanExporter"
- depends-on="mbeanServer">
- <property name="beans">
- <map>
- <entry key="CONFIG.SHIRDRN.ORG:name=config" value-ref="config" />
- <entry key="MX4J.SOURCEFORGE.COM:name=httpAdaptor" value-ref="httpAdaptor" />
- <!--
- <entry key="jdmk.sun.com:name=adaptorServer" value-ref="adaptorServer" />
- -->
- </map>
- </property>
- <property name="server" ref="mbeanServer" />
- <property name="assembler">
- <ref bean="assembler" />
- </property>
- </bean>
- <bean id="assembler"
- class="org.springframework.jmx.export.assembler.InterfaceBasedMBeanInfoAssembler">
- <property name="managedInterfaces">
- <list>
- <value>org.shirdrn.jmx.mx4j.SelectedMethodsInterface</value>
- </list>
- </property>
- </bean>
- <bean id="mbeanServer" class="org.springframework.jmx.support.MBeanServerFactoryBean" />
- <bean id="httpAdaptor" class="mx4j.tools.adaptor.http.HttpAdaptor">
- <property name="processor">
- <ref bean="xsltProcessor" />
- </property>
- <property name="host">
- <value>192.168.1.102</value>
- </property>
- <property name="port" value="9988" />
- </bean>
- <bean id="xsltProcessor" class="mx4j.tools.adaptor.http.XSLTProcessor" />
- <bean id="config" class="org.shirdrn.jmx.mx4j.MyConfiguration" />
- <!--
- <bean id="adaptorServer" class="com.sun.jdmk.comm.HtmlAdaptorServer">
- <property name="port">
- <value>9999</value>
- </property>
- </bean>
- -->
- </beans>
上面配置中,比较核心的是MX4J的HTTP适配器类:mx4j.tools.adaptor.http.HttpAdaptor,它有一个processor属性,使用MX4J已经实现的mx4j.tools.adaptor.http.XSLTProcessor来对其注入。XSLTProcessor实现了MX4J定义的XML转换成为浏览器可以解析的格式的文档,就Web网页。
通过MX4J的源码可以看到,在mx4j-3.0.2/src/tools/mx4j/tools/adaptor/http/xsl目录下面,可以看到MX4J定义的一些XSLT模板,例如serverbydomain.xsl为Web控制台首页模板:
- <?xml version="1.0"?>
- <!--
- Copyright (C) The MX4J Contributors.
- All rights reserved.
- This software is distributed under the terms of the MX4J License version 1.0.
- See the terms of the MX4J License in the documentation provided with this software.
- Author: Carlos Quiroz (tibu@users.sourceforge.net)
- Revision: $Revision: 1.2 $
- -->
- <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
- <xsl:output method="html" indent="yes" encoding="ISO-8859-1"/>
- <xsl:include href="common.xsl" mce_href="common.xsl"/>
- <xsl:include href="xalan-ext.xsl" mce_href="xalan-ext.xsl"/>
- <xsl:param name="html.stylesheet">stylesheet.css</xsl:param>
- <xsl:param name="html.stylesheet.type">text/css</xsl:param>
- <xsl:param name="head.title">serverbydomain.title</xsl:param>
- <!-- Invoked when a query error is produced -->
- <xsl:template match="Domain" name="error">
- <xsl:for-each select="Exception">
- <tr>
- <td class="serverbydomain_domainline" colspan="5">
- <xsl:call-template name="str">
- <xsl:with-param name="id">serverbydomain.error.query</xsl:with-param>
- <xsl:with-param name="p0">
- <xsl:value-of select="@errorMsg"/>
- </xsl:with-param>
- </xsl:call-template>
- </td>
- </tr>
- </xsl:for-each>
- </xsl:template>
- <!-- Invoked to display each domain -->
- <xsl:template match="Domain" name="domain">
- <xsl:for-each select="Domain">
- <xsl:sort data-type="text" order="ascending" select="@name"/>
- <tr>
- <td class="serverbydomain_domainline" colspan="5">
- <xsl:call-template name="str">
- <xsl:with-param name="id">serverbydomain.domain.label</xsl:with-param>
- <xsl:with-param name="p0">
- <xsl:value-of select="@name"/>
- </xsl:with-param>
- </xsl:call-template>
- </td>
- <xsl:call-template name="mbean"/>
- </tr>
- </xsl:for-each>
- </xsl:template>
- <!-- invoked for each mbean -->
- <xsl:template match="MBean" name="mbean">
- <xsl:for-each select="MBean">
- <xsl:sort data-type="text" order="ascending" select="@objectname"/>
- <xsl:variable name="classtype">
- <xsl:if test="(position() mod 2)=1">darkline</xsl:if>
- <xsl:if test="(position() mod 2)=0">clearline</xsl:if>
- </xsl:variable>
- <xsl:variable name="objectname">
- <xsl:call-template name="uri-encode">
- <xsl:with-param name="uri" select="@objectname"/>
- </xsl:call-template>
- </xsl:variable>
- <tr class="{$classtype}" width="100%">
- <td width="35%" align="left" class="serverbydomain_row">
- <a href="mbean?objectname={$objectname}" mce_href="mbean?objectname={$objectname}">
- <xsl:value-of select="@objectname"/>
- </a>
- </td>
- <td width="20%" align="left" class="serverbydomain_row">
- <p>
- <xsl:value-of select="@classname"/>
- </p>
- </td>
- <td width="35%" align="left" class="serverbydomain_row">
- <p>
- <xsl:value-of select="@description"/>
- </p>
- </td>
- <td width="10%" align="right" class="serverbydomain_row">
- <p>
- <a href="delete?objectname={$objectname}" mce_href="delete?objectname={$objectname}">
- <xsl:call-template name="str">
- <xsl:with-param name="id">serverbydomain.mbean.unregister</xsl:with-param>
- </xsl:call-template>
- </a>
- </p>
- </td>
- </tr>
- </xsl:for-each>
- </xsl:template>
- <!-- Main template -->
- <xsl:template match="Server">
- <html>
- <xsl:call-template name="head"/>
- <body>
- <table width="100%" cellpadding="0" cellspacing="0" border="0">
- <tr width="100%">
- <td>
- <xsl:call-template name="toprow"/>
- <xsl:call-template name="tabs">
- <xsl:with-param name="selection">server</xsl:with-param>
- </xsl:call-template>
- <xsl:variable name="query">
- <xsl:call-template name="str">
- <xsl:with-param name="id">serverbydomain.server.query</xsl:with-param>
- </xsl:call-template>
- </xsl:variable>
- <table width="100%" cellpadding="0" cellspacing="0" border="0">
- <tr>
- <td class="page_title">
- <xsl:call-template name="str">
- <xsl:with-param name="id">serverbydomain.server.title</xsl:with-param>
- </xsl:call-template>
- </td>
- <form action="serverbydomain">
- <td align="right" class="page_title">
- <xsl:call-template name="str">
- <xsl:with-param name="id">serverbydomain.server.filter</xsl:with-param>
- </xsl:call-template>
- <input type="text" name="querynames" value="*:*"/>
- <input type="submit" value="{$query}"/>
- </td>
- </form>
- </tr>
- </table>
- <table width="100%" cellpadding="0" cellspacing="0" border="0">
- <xsl:call-template name="domain"/>
- <xsl:call-template name="error"/>
- </table>
- <xsl:call-template name="bottom"/>
- </td>
- </tr>
- </table>
- </body>
- </html>
- </xsl:template>
- </xsl:stylesheet>
Spring配置中通过实例化一个HttpAdaptor,注册到MBean Server中,实现基于HTTP协议远程访问管理和监控。org.shirdrn.jmx.mx4j.MyConfiguration我们定义的一个MBean,也注册到MBean Server中,实现JMX的管理与监控,代码如下所示:
- package org.shirdrn.jmx.mx4j;
- public class MyConfiguration {
- private long id = System.currentTimeMillis();
- private String name;
- public MyConfiguration() {
- super();
- }
- public MyConfiguration(long id, String name) {
- super();
- this.id = id;
- this.name = name;
- }
- public long getId() {
- return id;
- }
- public void setId(long id) {
- this.id = id;
- }
- public String getName() {
- return name;
- }
- public void setName(String name) {
- // 通过JMX管理调用时,更新id的值
- this.id = System.currentTimeMillis();
- this.name = name;
- }
- public String show() {
- StringBuffer sb = new StringBuffer().append("id=").append(id).append(
- ", name=").append(name);
- System.out.println("show()=" + sb.toString());
- return sb.toString();
- }
- }
但是,Spring配置中的org.springframework.jmx.export.assembler.InterfaceBasedMBeanInfoAssembler对MBean暴露的操作进行了限制,主要是通过我们定义的接口org.shirdrn.jmx.mx4j.SelectedMethodsInterface来指定需要将MBean的哪些内容暴露给JMX管理,接口如下所示:
- package org.shirdrn.jmx.mx4j;
- public interface SelectedMethodsInterface {
- public long getId();
- public void setName(String name);
- public String getName();
- public void show();
- }
最后,我们可以初始化Spring的IOC容器,启动MX4J的HttpAdaptor服务,实现通过Web控制台的JMX管理,代码如下所示:
- package org.shirdrn.jmx.mx4j;
- import <a href="http://lib.csdn.net/base/17" class='replace_word' title="Java EE知识库" target='_blank' style='color:#df3434; font-weight:bold;'>Java</a>.io.IOException;
- import javax.management.MalformedObjectNameException;
- import mx4j.tools.adaptor.http.HttpAdaptor;
- import org.springframework.context.ApplicationContext;
- import org.springframework.context.support.ClassPathXmlApplicationContext;
- public class JMXTest {
- public static void main(String[] args) throws IOException,
- MalformedObjectNameException, Exception {
- ApplicationContext ctx = new ClassPathXmlApplicationContext(
- new String[] { "org/shirdrn/jmx/mx4j/applicationContext.xml" });
- HttpAdaptor httpAdaptor = (HttpAdaptor) ctx.getBean("httpAdaptor");
- httpAdaptor.start();
- }
- }
启动成功后,可以通过浏览http://192.168.1.102:9988,可以看到我们注册的MBean,并对其进行管理和监控。