技术开发 频道

扩展 Spring 的 JMX 支持

    对管理员友好的消息

    这个扩展的描述符可以几乎直接关联属性和操作。描述符方法优于内省式方法的主要一点是可以提供更特定的消息。通知描述符的配置选项有赖于类型(XML)属性的命名规范。实际的名字是任意的,但是代码会被类型中的 set.name、before.name 和 after.name 样式触发。在这种情况下,我将 set 通知与 propertyValue (JMX)属性关联,将 before 与 after 通知与 startService() 与 stopService() 方法关联。同样,这些扩展使我可以很好利用描述性的消息。

    在清单 5 中,可以看到定义了一个属性和两个方法。通知描述符定义了方法的之前和之后事件以及一个属性设置通知:

    清单 5. ExampleService.mbean.xml  

<?xml version="1.0"?> <mbean name="ExampleService" description="Example Service" type="com.claudeduguay.jmx.demo.server.ExampleService"> <attribute name="propertyValue" description="Property Value Access" type="java.lang.String" readable="true" writable="true" /> <operation name="stopService" description="Stop Example Service" /> <operation name="startService" description="Start Example Service" /> <notification name="PropertyValueSet" types="example.service.set.propertyValue" description="PropertyValue was set" /> <notification name="BeforeStartService" types="example.service.before.startService" description="Example Service is Starting" /> <notification name="AfterStartService" types="example.service.after.startService" description="Example Service is Started" /> <notification name="BeforeStopService" types="example.service.before.stopService" description="Example Service is Stopping" /> <notification name="AfterStopService" types="example.service.after.stopService" description="Example Service is Stopped" /> </mbean>
    配置服务器

    要在客户机/服务器环境中运行这个例子,需要配置和启动一个 MBeanServer 实例。为此,我使用 Java 5.0 MBeanServer 实例,它保证我可以使用 JVM 中提供的管理扩展,同时管理自己的代码。如果愿意,还可以运行 MBeanServer 的多个实例,您愿意的话也可以自己试一试作为练习。

    就像 Java 5.0 一样,Spring 框架使您可以配置自己的 MBeanServer 实例。我选择使用 Java 5.0,因为它支持 JSR-160 连接器,我的客户机代码会需要它。

    清单 6. SpringJmxServer
package com.claudeduguay.jmx.demo.server; import org.springframework.context.*; import org.springframework.context.support.*; import mx4j.tools.adaptor.http.*; /* * To use the SpringJmxServer, use the following command line * arguments to activate the Java 1.5 JMX Server. * * -Dcom.sun.management.jmxremote.port=8999 * -Dcom.sun.management.jmxremote.ssl=false * -Dcom.sun.management.jmxremote.authenticate=false */ public class SpringJmxServer { public static void main(String[] args) throws Exception { String SPRING_FILE = "com/claudeduguay/jmx/demo/server/SpringJmxServer.xml"; ApplicationContext context = new ClassPathXmlApplicationContext(SPRING_FILE); HttpAdaptor httpAdaptor = (HttpAdaptor)context.getBean("HttpAdaptor"); httpAdaptor.start(); } }

    由于有了 MBeanDescriptorEnabledExporter,服务器的 Spring 配置文件非常简单。除了声明 ExampleService,我增加了开放一个 HTTP 适配器和连接 XSLTProcessor 到 HttpAdaptor 所需要的 MX4J 项。注意这是 Spring 的 IOC 实现非常有用的一个领域。清单 7 显示了我的 SpringJmxServer 实例的 Spring 配置文件:

    清单 7. SpringJmxServer.xml

<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd"> <beans> <bean id="exporter" class= "com.claudeduguay.mbeans.spring.MBeanDescriptorEnabledExporter"> <property name="beans"> <map> <entry key="Services:name=ExampleService" value-ref="ExampleService" /> <entry key="MX4J:name=HttpAdaptor" value-ref="HttpAdaptor" /> <entry key="MX4J:name=XSLTProcessor" value-ref="XSLTProcessor" /> </map> </property> </bean> <bean id="XSLTProcessor" class="mx4j.tools.adaptor.http.XSLTProcessor" /> <bean id="HttpAdaptor" class="mx4j.tools.adaptor.http.HttpAdaptor"> <property name="processor" ref="XSLTProcessor"/> <property name="port" value="8080"/> </bean> <bean id="ExampleService" class="com.claudeduguay.jmx.demo.server.ExampleService" /> </beans>

    如果愿意(假定您遵循了我的设置),那么现在就可以运行这个服务器了。它会注册 ExampleService 并运行 HTTP 适配器。不要忘记使用注释中提到的命令行参数启动 Java 5.0 MBeanServer,否则会得到默认实例,客户机示例就不能工作了。

    运行客户机代码

    启动服务器后,可以运行如清单 8 所示的客户机代码看看会发生什么。这段代码实现了 JMX NotificationListener 接口,这样就可以交互式地看到所发生的事情。连接后,可以注册监听器,然后触发几个调用、启动和停止服务、设置和取得属性。在每一种情况下,都应当在控制台上看到一个确认操作的通知消息。 

    清单 8. SpringJmxClient

package com.claudeduguay.jmx.demo.client; import java.util.*; import javax.management.*; import javax.management.remote.*; public class SpringJmxClient implements NotificationListener { public void handleNotification( Notification notification, Object handback) { System.out.println( "Notification: " + notification.getMessage()); } public static void main(String[] args) throws Exception { SpringJmxClient listener = new SpringJmxClient(); String address = "service:jmx:rmi:///jndi/rmi://localhost:8999/jmxrmi"; JMXServiceURL serviceURL = new JMXServiceURL(address); Map<String,Object> environment = null; JMXConnector connector = JMXConnectorFactory.connect(serviceURL, environment); MBeanServerConnection mBeanConnection = connector.getMBeanServerConnection(); ObjectName exampleServiceName = ObjectName.getInstance("Services:name=ExampleService"); mBeanConnection.addNotificationListener( exampleServiceName, listener, null, null); mBeanConnection.invoke( exampleServiceName, "startService", null, null); mBeanConnection.setAttribute(exampleServiceName, new Attribute("propertyValue", "new value")); System.out.println(mBeanConnection.getAttribute( exampleServiceName, "propertyValue")); mBeanConnection.invoke( exampleServiceName, "stopService", null, null); } }
    由于 HTTP 适配器也是可用的,可以试着使用 MX4J (通过一个到端口 8080 的浏览器连接)管理同样的方法和属性。如果同时让客户机代码运行,那么也会看到这些操作的通知。

    结束语

    在本文中,我展示了如何扩展 Spring 的 JMX 支持以满足应用程序的特定需求。在这里,我使用了 Spring 的基于容器的体系结构和 AOP 框架来为 JMX 方法和属性增加通知事件。当然,我只触及到了 Spring JMX 能力的皮毛。还可以有许多其他扩展,Spring 和 JMX 都是很大的主题,每一个都值得进一步研究。我建议您研究本文的源代码并参阅后面 参考资料 一节以了解更多关于 Spring JMX 和相关技术的内容。
0
相关文章